1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/*
* 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 <Swiften/Base/foreach.h>
#include "Swiften/Disco/EntityCapsProvider.h"
#include <Swiften/JID/JID.h>
#include <Swiften/Elements/StreamInitiationFileInfo.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) {
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(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<ConnectionServer> 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<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)) {
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();
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<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(receipient, bytestream, fileInfo);
}
}
|