summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/FileTransfer/FileTransferManagerImpl.cpp')
-rw-r--r--Swiften/FileTransfer/FileTransferManagerImpl.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
new file mode 100644
index 0000000..83320b2
--- /dev/null
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/FileTransfer/FileTransferManagerImpl.h>
+
+#include <boost/bind.hpp>
+#include <boost/cstdint.hpp>
+
+#include <Swiften/Base/foreach.h>
+#include "Swiften/Disco/EntityCapsProvider.h"
+#include <Swiften/JID/JID.h>
+#include <Swiften/Elements/StreamInitiationFileInfo.h>
+#include <Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h>
+#include <Swiften/FileTransfer/ConnectivityManager.h>
+#include <Swiften/FileTransfer/OutgoingFileTransferManager.h>
+#include <Swiften/FileTransfer/IncomingFileTransferManager.h>
+#include <Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h>
+#include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h>
+#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
+#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
+#include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h>
+#include <Swiften/Presence/PresenceOracle.h>
+#include <Swiften/Elements/Presence.h>
+#include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Network/ConnectionServerFactory.h>
+#include <Swiften/Network/HostAddress.h>
+#include <Swiften/Network/NATTraverser.h>
+
+namespace Swift {
+
+FileTransferManagerImpl::FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, NATTraverser* natTraverser) : ownJID(ownFullJID), jingleSM(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), presenceOracle(presOracle), timerFactory(timerFactory), connectionFactory(connectionFactory), connectionServerFactory(connectionServerFactory), natTraverser(natTraverser), bytestreamServer(NULL), s5bProxyFinder(NULL) {
+ assert(!ownFullJID.isBare());
+
+ connectivityManager = new ConnectivityManager(natTraverser);
+ bytestreamRegistry = new SOCKS5BytestreamRegistry();
+ bytestreamProxy = new SOCKS5BytestreamProxy(connectionFactory, timerFactory);
+
+ localCandidateGeneratorFactory = new DefaultLocalJingleTransportCandidateGeneratorFactory(connectivityManager, bytestreamRegistry, bytestreamProxy, ownFullJID);
+ remoteCandidateSelectorFactory = new DefaultRemoteJingleTransportCandidateSelectorFactory(connectionFactory, timerFactory);
+ outgoingFTManager = new OutgoingFileTransferManager(jingleSM, iqRouter, capsProvider, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy);
+ incomingFTManager = new IncomingFileTransferManager(jingleSM, iqRouter, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy, timerFactory);
+ incomingFTManager->onIncomingFileTransfer.connect(onIncomingFileTransfer);
+}
+
+FileTransferManagerImpl::~FileTransferManagerImpl() {
+ if (s5bProxyFinder) {
+ s5bProxyFinder->stop();
+ delete s5bProxyFinder;
+ }
+ if (bytestreamServer) {
+ bytestreamServer->stop();
+ delete bytestreamServer;
+ }
+ delete incomingFTManager;
+ delete outgoingFTManager;
+ delete remoteCandidateSelectorFactory;
+ delete localCandidateGeneratorFactory;
+ delete connectivityManager;
+}
+
+void FileTransferManagerImpl::startListeningOnPort(int port) {
+ // TODO: create a server for each interface we're on
+ SWIFT_LOG(debug) << "Start listening on port " << port << " and hope it's not in use." << std::endl;
+ boost::shared_ptr<ConnectionServer> server = connectionServerFactory->createConnectionServer(HostAddress("0.0.0.0"), port);
+ server->start();
+ bytestreamServer = new SOCKS5BytestreamServer(server, bytestreamRegistry);
+ bytestreamServer->start();
+ connectivityManager->addListeningPort(port);
+
+ s5bProxyFinder = new SOCKS5BytestreamProxyFinder(ownJID.getDomain(), iqRouter);
+ s5bProxyFinder->onProxyFound.connect(boost::bind(&FileTransferManagerImpl::addS5BProxy, this, _1));
+ s5bProxyFinder->start();
+}
+
+void FileTransferManagerImpl::addS5BProxy(S5BProxyRequest::ref proxy) {
+ bytestreamProxy->addS5BProxy(proxy);
+}
+
+boost::optional<JID> FileTransferManagerImpl::highestPriorityJIDSupportingFileTransfer(const JID& bareJID) {
+ JID fullReceipientJID;
+ int priority = INT_MIN;
+
+ //getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
+ std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
+
+ //iterate over them
+ foreach(Presence::ref pres, presences) {
+ if (pres->getPriority() > priority) {
+ // look up caps from the jid
+ DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
+ if (info && info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) && (info->hasFeature(DiscoInfo::JingleTransportsIBBFeature) || info->hasFeature(DiscoInfo::JingleTransportsS5BFeature))) {
+
+ priority = pres->getPriority();
+ fullReceipientJID = pres->getFrom();
+ }
+ }
+ }
+
+ return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
+}
+
+OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer(const JID& to, const boost::filesystem::path& filepath, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream) {
+ std::string filename = filepath.filename();
+ boost::uintmax_t sizeInBytes = boost::filesystem::file_size(filepath);
+ boost::posix_time::ptime lastModified = boost::posix_time::from_time_t(boost::filesystem::last_write_time(filepath));
+ return createOutgoingFileTransfer(to, filename, description, sizeInBytes, lastModified, bytestream);
+}
+
+OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer(const JID& to, const std::string& filename, const std::string& description, const boost::uintmax_t sizeInBytes, const boost::posix_time::ptime& lastModified, boost::shared_ptr<ReadBytestream> bytestream) {
+ StreamInitiationFileInfo fileInfo;
+ fileInfo.setDate(lastModified);
+ fileInfo.setSize(sizeInBytes);
+ fileInfo.setName(filename);
+ fileInfo.setDescription(description);
+
+ JID receipient = to;
+
+ if(receipient.isBare()) {
+ boost::optional<JID> fullJID = highestPriorityJIDSupportingFileTransfer(receipient);
+ if (fullJID.is_initialized()) {
+ receipient = fullJID.get();
+ } else {
+ return OutgoingFileTransfer::ref();
+ }
+ }
+
+ return outgoingFTManager->createOutgoingFileTransfer(ownJID, receipient, bytestream, fileInfo);
+}
+
+}