/* * Copyright (c) 2011 Tobias Markmann * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #include #include #include #include "Swiften/Disco/EntityCapsProvider.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Swift { FileTransferManagerImpl::FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, PlatformNATTraversalWorker* natTraversalWorker) : ownJID(ownFullJID), jingleSM(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), presenceOracle(presOracle), timerFactory(timerFactory), connectionFactory(connectionFactory), connectionServerFactory(connectionServerFactory), natTraversalWorker(natTraversalWorker), bytestreamServer(NULL) { assert(!ownFullJID.isBare()); connectivityManager = new ConnectivityManager(natTraversalWorker); bytestreamRegistry = new SOCKS5BytestreamRegistry(); bytestreamProxy = new SOCKS5BytestreamProxy(connectionFactory, timerFactory); localCandidateGeneratorFactory = new DefaultLocalJingleTransportCandidateGeneratorFactory(connectivityManager, bytestreamRegistry, bytestreamProxy, ownFullJID); remoteCandidateSelectorFactory = new DefaultRemoteJingleTransportCandidateSelectorFactory(connectionFactory, timerFactory); outgoingFTManager = new OutgoingFileTransferManager(ownJID, jingleSM, iqRouter, capsProvider, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy); incomingFTManager = new IncomingFileTransferManager(ownJID, jingleSM, iqRouter, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy, timerFactory); incomingFTManager->onIncomingFileTransfer.connect(onIncomingFileTransfer); } FileTransferManagerImpl::~FileTransferManagerImpl() { if (bytestreamServer) { bytestreamServer->stop(); } 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 server = connectionServerFactory->createConnectionServer(HostAddress("0.0.0.0"), port); server->start(); bytestreamServer = new SOCKS5BytestreamServer(server, bytestreamRegistry); bytestreamServer->start(); connectivityManager->addListeningPort(port); } void FileTransferManagerImpl::addS5BProxy(S5BProxyRequest::ref proxy) { bytestreamProxy->addS5BProxy(proxy); } boost::optional 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 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)) { priority = pres->getPriority(); fullReceipientJID = pres->getFrom(); } } } return fullReceipientJID.isValid() ? boost::optional(fullReceipientJID) : boost::optional(); } OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer(const JID& to, const boost::filesystem::path& filepath, const std::string& description, boost::shared_ptr bytestream) { std::string filename = filepath.filename(); 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 uintmax_t sizeInBytes, const boost::posix_time::ptime& lastModified, boost::shared_ptr bytestream) { StreamInitiationFileInfo fileInfo; fileInfo.setDate(lastModified); fileInfo.setSize(sizeInBytes); fileInfo.setName(filename); fileInfo.setDescription(description); JID receipient = to; if(receipient.isBare()) { boost::optional fullJID = highestPriorityJIDSupportingFileTransfer(receipient); if (fullJID.is_initialized()) { receipient = fullJID.get(); } else { return OutgoingFileTransfer::ref(); } } return outgoingFTManager->createOutgoingFileTransfer(receipient, bytestream, fileInfo); } }