diff options
7 files changed, 141 insertions, 233 deletions
diff --git a/src/com/isode/stroke/filetransfer/FileTransferManagerImpl.java b/src/com/isode/stroke/filetransfer/FileTransferManagerImpl.java index 58ea74e..da5e120 100644 --- a/src/com/isode/stroke/filetransfer/FileTransferManagerImpl.java +++ b/src/com/isode/stroke/filetransfer/FileTransferManagerImpl.java @@ -88,8 +88,7 @@ public class FileTransferManagerImpl extends FileTransferManager { timerFactory, crypto); incomingFTManager = new IncomingFileTransferManager( - jingleSessionManager, - iqRouter, + jingleSessionManager, transporterFactory, timerFactory, crypto); diff --git a/src/com/isode/stroke/filetransfer/IBBSendSession.java b/src/com/isode/stroke/filetransfer/IBBSendSession.java index 5a812ff..bb44006 100644 --- a/src/com/isode/stroke/filetransfer/IBBSendSession.java +++ b/src/com/isode/stroke/filetransfer/IBBSendSession.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2015 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -12,6 +12,7 @@ package com.isode.stroke.filetransfer; import com.isode.stroke.signals.Signal1; +import com.isode.stroke.signals.SignalConnection; import com.isode.stroke.signals.Slot2; import com.isode.stroke.signals.Slot; import com.isode.stroke.jid.JID; @@ -31,8 +32,9 @@ public class IBBSendSession { private int sequenceNumber; private boolean active; private boolean waitingForData; + private SignalConnection currentRequestOnResponseConnection; - public IBBSendSession(final String id, final JID from, final JID to, ReadBytestream bytestream, IQRouter router) { + public IBBSendSession(final String id, final JID from, final JID to, ReadBytestream bytestream, IQRouter router) { this.id = id; this.from = from; this.to = to; @@ -52,7 +54,7 @@ public class IBBSendSession { public void start() { IBBRequest request = IBBRequest.create(from, to, IBB.createIBBOpen(id, (int)(blockSize)), router); - request.onResponse.connect(new Slot2<IBB, ErrorPayload>() { + currentRequestOnResponseConnection = request.onResponse.connect(new Slot2<IBB, ErrorPayload>() { @Override public void call(IBB b, ErrorPayload e) { handleIBBResponse(b, e); @@ -66,6 +68,10 @@ public class IBBSendSession { if (active && router.isAvailable()) { IBBRequest.create(from, to, IBB.createIBBClose(id), router).send(); } + if (currentRequestOnResponseConnection != null) { + currentRequestOnResponseConnection.disconnect(); + currentRequestOnResponseConnection = null; + } finish(null); } @@ -83,8 +89,11 @@ public class IBBSendSession { public final Signal1<FileTransferError> onFinished = new Signal1<FileTransferError>(); public final Signal1<Integer> onBytesSent = new Signal1<Integer>(); - - private void handleIBBResponse(IBB ibb, ErrorPayload error) { + private void handleIBBResponse(IBB ibb, ErrorPayload error) { + if (currentRequestOnResponseConnection != null) { + currentRequestOnResponseConnection.disconnect(); + currentRequestOnResponseConnection = null; + } if (error == null && active) { if (!bytestream.isFinished()) { sendMoreData(); diff --git a/src/com/isode/stroke/filetransfer/IncomingFileTransferManager.java b/src/com/isode/stroke/filetransfer/IncomingFileTransferManager.java index ffdf86e..7166d67 100644 --- a/src/com/isode/stroke/filetransfer/IncomingFileTransferManager.java +++ b/src/com/isode/stroke/filetransfer/IncomingFileTransferManager.java @@ -30,20 +30,17 @@ import java.util.Vector; public class IncomingFileTransferManager implements IncomingJingleSessionHandler { private JingleSessionManager jingleSessionManager; - private IQRouter router; private FileTransferTransporterFactory transporterFactory; private TimerFactory timerFactory; private CryptoProvider crypto; private Logger logger_ = Logger.getLogger(this.getClass().getName()); public IncomingFileTransferManager( - JingleSessionManager jingleSessionManager, - IQRouter router, + JingleSessionManager jingleSessionManager, FileTransferTransporterFactory transporterFactory, TimerFactory timerFactory, CryptoProvider crypto) { this.jingleSessionManager = jingleSessionManager; - this.router = router; this.transporterFactory = transporterFactory; this.timerFactory = timerFactory; this.crypto = crypto; diff --git a/src/com/isode/stroke/filetransfer/LocalJingleTransportCandidateGenerator.java b/src/com/isode/stroke/filetransfer/LocalJingleTransportCandidateGenerator.java index 3839b26..a4c4623 100644 --- a/src/com/isode/stroke/filetransfer/LocalJingleTransportCandidateGenerator.java +++ b/src/com/isode/stroke/filetransfer/LocalJingleTransportCandidateGenerator.java @@ -22,8 +22,11 @@ import com.isode.stroke.signals.SignalConnection; import com.isode.stroke.signals.Slot1; import com.isode.stroke.signals.Slot; import com.isode.stroke.signals.Signal1; + +import java.net.Inet6Address; import java.util.Vector; import java.util.logging.Logger; + import com.isode.stroke.network.HostAddressPort; import com.isode.stroke.network.HostAddress; import com.isode.stroke.elements.JingleS5BTransportPayload; @@ -172,7 +175,11 @@ public class LocalJingleTransportCandidateGenerator { // get direct candidates Vector<HostAddressPort> directCandidates = s5bServerManager.getHostAddressPorts(); for(HostAddressPort addressPort : directCandidates) { - JingleS5BTransportPayload.Candidate candidate = new JingleS5BTransportPayload.Candidate(); + if (addressPort.getAddress().getInetAddress() instanceof Inet6Address + && addressPort.getAddress().getInetAddress().isLinkLocalAddress()) { + continue; + } + JingleS5BTransportPayload.Candidate candidate = new JingleS5BTransportPayload.Candidate(); candidate.type = JingleS5BTransportPayload.Candidate.Type.DirectType; candidate.jid = ownJID; candidate.hostPort = addressPort; diff --git a/src/com/isode/stroke/filetransfer/OutgoingSIFileTransfer.java b/src/com/isode/stroke/filetransfer/OutgoingSIFileTransfer.java deleted file mode 100644 index 4ba17de..0000000 --- a/src/com/isode/stroke/filetransfer/OutgoingSIFileTransfer.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2010-2015 Isode Limited. - * All rights reserved. - * See the COPYING file for more information. - */ -/* - * Copyright (c) 2015 Tarun Gupta. - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -package com.isode.stroke.filetransfer; - -import com.isode.stroke.jid.JID; -import com.isode.stroke.queries.IQRouter; -import com.isode.stroke.signals.Signal1; -import com.isode.stroke.elements.ErrorPayload; -import com.isode.stroke.elements.StreamInitiation; -import com.isode.stroke.elements.Bytestreams; - -public class OutgoingSIFileTransfer implements OutgoingFileTransfer { - - private long fileSizeInBytes = 0; //FileTransferVariables - private String filename = ""; //FileTransferVariables - - /** - * FileTransferMethod. - */ - @Override - public String getFileName() { - return filename; - } - - /** - * FileTransferMethod. - */ - @Override - public long getFileSizeInBytes() { - return fileSizeInBytes; - } - - /** - * FileTransferMethod. - */ - @Override - public void setFileInfo(final String name, long size) { - this.filename = name; - this.fileSizeInBytes = size; - } - - private String id = ""; - private JID from; - private JID to; - private String name = ""; - private long size; - private String description = ""; - private ReadBytestream bytestream; - private IQRouter iqRouter; - private SOCKS5BytestreamServer socksServer; - private IBBSendSession ibbSession; - - public OutgoingSIFileTransfer(final String id, final JID from, final JID to, final String name, long size, final String description, ReadBytestream bytestream, IQRouter iqRouter, SOCKS5BytestreamServer socksServer) { - this.id = id; - this.from = from; - this.to = to; - this.name = name; - this.size = size; - this.description = description; - this.bytestream = bytestream; - this.iqRouter = iqRouter; - this.socksServer = socksServer; - this.ibbSession = ibbSession; - } - - /** - * OutgoingFileTransferMethod. - */ - @Override - public void start() { - /* - StreamInitiation::ref streamInitiation(new StreamInitiation()); - streamInitiation.setID(id); - 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); - request.onResponse.connect(boost::bind(&OutgoingSIFileTransfer::handleStreamInitiationRequestResponse, this, _1, _2)); - request.send(); - */ - } - - public void stop() { - } - - public final Signal1<FileTransferError> onFinished = new Signal1<FileTransferError>(); - - private void handleStreamInitiationRequestResponse(StreamInitiation stream, ErrorPayload error) { - /* - if (error) { - finish(FileTransferError()); - } - else { - if (response->getRequestedMethod() == "http://jabber.org/protocol/bytestreams") { - socksServer->addReadBytestream(id, from, to, bytestream); - Bytestreams::ref bytestreams(new Bytestreams()); - bytestreams->setStreamID(id); - HostAddressPort addressPort = socksServer->getAddressPort(); - bytestreams->addStreamHost(Bytestreams::StreamHost(addressPort.getAddress().toString(), from, addressPort.getPort())); - BytestreamsRequest::ref request = BytestreamsRequest::create(to, bytestreams, iqRouter); - request->onResponse.connect(boost::bind(&OutgoingSIFileTransfer::handleBytestreamsRequestResponse, this, _1, _2)); - request->send(); - } - else if (response->getRequestedMethod() == "http://jabber.org/protocol/ibb") { - ibbSession = boost::make_shared<IBBSendSession>(id, from, to, bytestream, iqRouter); - ibbSession->onFinished.connect(boost::bind(&OutgoingSIFileTransfer::handleIBBSessionFinished, this, _1)); - ibbSession->start(); - } - } - */ - } - - private void handleBytestreamsRequestResponse(Bytestreams stream, ErrorPayload error) { - /* - if (error) { - finish(FileTransferError()); - } - */ - //socksServer->onTransferFinished.connect(); - } - - private void finish(FileTransferError error) { - /* - if (ibbSession) { - ibbSession->onFinished.disconnect(boost::bind(&OutgoingSIFileTransfer::handleIBBSessionFinished, this, _1)); - ibbSession.reset(); - } - socksServer->removeReadBytestream(id, from, to); - onFinished(error); - */ - } - - private void handleIBBSessionFinished(FileTransferError error) { - //finish(error); - } - - public void cancel() { - - } -}
\ No newline at end of file diff --git a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamProxiesManager.java b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamProxiesManager.java index eab3031..f541222 100644 --- a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamProxiesManager.java +++ b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamProxiesManager.java @@ -16,29 +16,29 @@ package com.isode.stroke.filetransfer; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; +import java.util.logging.Logger; + +import com.isode.stroke.elements.S5BProxyRequest; +import com.isode.stroke.jid.JID; import com.isode.stroke.network.Connection; import com.isode.stroke.network.ConnectionFactory; -import com.isode.stroke.network.DomainNameResolver; -import com.isode.stroke.network.TimerFactory; -import com.isode.stroke.network.HostAddressPort; -import com.isode.stroke.network.DomainNameResolveError; import com.isode.stroke.network.DomainNameAddressQuery; +import com.isode.stroke.network.DomainNameResolveError; +import com.isode.stroke.network.DomainNameResolver; import com.isode.stroke.network.HostAddress; +import com.isode.stroke.network.HostAddressPort; +import com.isode.stroke.network.TimerFactory; import com.isode.stroke.queries.IQRouter; -import com.isode.stroke.session.Session; -import com.isode.stroke.signals.Slot1; -import com.isode.stroke.signals.Slot2; import com.isode.stroke.signals.Signal; import com.isode.stroke.signals.SignalConnection; -import com.isode.stroke.elements.S5BProxyRequest; -import com.isode.stroke.jid.JID; - -import java.util.Iterator; -import java.util.Vector; -import java.util.Collection; -import java.util.Map; -import java.util.HashMap; -import java.util.logging.Logger; +import com.isode.stroke.signals.Slot1; +import com.isode.stroke.signals.Slot2; /** * - manages list of working S5B proxies @@ -53,8 +53,6 @@ public class SOCKS5BytestreamProxiesManager { private JID serviceRoot_; private Logger logger_ = Logger.getLogger(this.getClass().getName()); - // TODO plonk this into the pair or not - // TODO think what this is trying to do? private static class Pair { public JID jid; public SOCKS5BytestreamClientSession sock5; @@ -64,7 +62,8 @@ public class SOCKS5BytestreamProxiesManager { private Map<String, Collection<Pair> > proxySessions_ = new HashMap<String, Collection<Pair> >(); - /** + private SignalConnection onProxiesFoundConnection; + /** * Map between {@link SOCKS5BytestreamClientSession} and a {@link SignalConnection} to their * {@link SOCKS5BytestreamClientSession#onSessionReady} */ @@ -183,31 +182,37 @@ public class SOCKS5BytestreamProxiesManager { } public final Signal onDiscoveredProxiesChanged = new Signal(); - - private void handleProxyFound(final S5BProxyRequest proxy) { - if (proxy != null) { - if (new HostAddress(proxy.getStreamHost().host).isValid()) { - addS5BProxy(proxy); - onDiscoveredProxiesChanged.emit(); - } - else { - DomainNameAddressQuery resolveRequest = resolver_.createAddressQuery(proxy.getStreamHost().host); - resolveRequest.onResult.connect(new Slot2<Collection<HostAddress>, DomainNameResolveError>() { - @Override - public void call(Collection<HostAddress> c, DomainNameResolveError d) { - handleNameLookupResult(c, d, proxy); - } - }); - resolveRequest.run(); - } - } - else { - onDiscoveredProxiesChanged.emit(); - } - proxyFinder_.stop(); - proxyFinder_ = null; + + private void handleProxiesFound(Collection<? extends S5BProxyRequest> proxyHosts) { + if (onProxiesFoundConnection != null) { + onProxiesFoundConnection.disconnect(); + onProxiesFoundConnection = null; + } + for (final S5BProxyRequest proxy : proxyHosts) { + if (proxy != null) { + if (new HostAddress(proxy.getStreamHost().host).isValid()) { + addS5BProxy(proxy); + onDiscoveredProxiesChanged.emit(); + } + else { + DomainNameAddressQuery resolveRequest = resolver_.createAddressQuery(proxy.getStreamHost().host); + resolveRequest.onResult.connect(new Slot2<Collection<HostAddress>, DomainNameResolveError>() { + @Override + public void call(Collection<HostAddress> c, DomainNameResolveError d) { + handleNameLookupResult(c, d, proxy); + } + }); + resolveRequest.run(); + } + } + } + proxyFinder_.stop(); + proxyFinder_ = null; + if (proxyHosts.isEmpty()) { + onDiscoveredProxiesChanged.emit(); + } } - + private void handleNameLookupResult(final Collection<HostAddress> addresses, DomainNameResolveError error, S5BProxyRequest proxy) { if (error != null) { onDiscoveredProxiesChanged.emit(); @@ -215,7 +220,6 @@ public class SOCKS5BytestreamProxiesManager { else { if (addresses.isEmpty()) { logger_.warning("S5B proxy hostname does not resolve.\n"); - onDiscoveredProxiesChanged.emit(); } else { // generate proxy per returned address @@ -226,18 +230,17 @@ public class SOCKS5BytestreamProxiesManager { proxyForAddress.setStreamHost(streamHost); addS5BProxy(proxyForAddress); } - onDiscoveredProxiesChanged.emit(); } + onDiscoveredProxiesChanged.emit(); } } private void queryForProxies() { proxyFinder_ = new SOCKS5BytestreamProxyFinder(serviceRoot_, iqRouter_); - - proxyFinder_.onProxyFound.connect(new Slot1<S5BProxyRequest>() { + onProxiesFoundConnection = proxyFinder_.onProxiesFound.connect(new Slot1<List<S5BProxyRequest>>() { @Override - public void call(S5BProxyRequest s) { - handleProxyFound(s); + public void call(List<S5BProxyRequest> s) { + handleProxiesFound(s); } }); proxyFinder_.start(); diff --git a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamProxyFinder.java b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamProxyFinder.java index d856a2f..e880bfb 100644 --- a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamProxyFinder.java +++ b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamProxyFinder.java @@ -16,32 +16,45 @@ package com.isode.stroke.filetransfer; -import com.isode.stroke.network.HostAddressPort; -import com.isode.stroke.elements.S5BProxyRequest; -import com.isode.stroke.elements.ErrorPayload; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; + +import com.isode.stroke.disco.DiscoServiceWalker; import com.isode.stroke.elements.DiscoInfo; +import com.isode.stroke.elements.ErrorPayload; import com.isode.stroke.elements.IQ; -import com.isode.stroke.disco.DiscoServiceWalker; -import com.isode.stroke.queries.IQRouter; +import com.isode.stroke.elements.S5BProxyRequest; +import com.isode.stroke.jid.JID; import com.isode.stroke.queries.GenericRequest; +import com.isode.stroke.queries.IQRouter; import com.isode.stroke.signals.Signal1; import com.isode.stroke.signals.SignalConnection; +import com.isode.stroke.signals.Slot; import com.isode.stroke.signals.Slot2; -import com.isode.stroke.jid.JID; -import java.util.Vector; -import java.util.logging.Logger; /* * This class is designed to find possible SOCKS5 bytestream proxies which are used for peer-to-peer data transfers in * restrictive environments. */ public class SOCKS5BytestreamProxyFinder { - + private JID service; private IQRouter iqRouter; private DiscoServiceWalker serviceWalker; - private Vector<GenericRequest<S5BProxyRequest> > requests = new Vector<GenericRequest<S5BProxyRequest>>(); + private final List<S5BProxyRequest> proxyHosts = new ArrayList<S5BProxyRequest>(); + private final Set<GenericRequest<S5BProxyRequest>> pendingRequests = new HashSet<GenericRequest<S5BProxyRequest>>(); + private SignalConnection onServiceFoundConnection; + private SignalConnection onWalkCompleteConnection; + private final Map<GenericRequest<S5BProxyRequest>,SignalConnection> requestOnResponseConnections + = new HashMap<GenericRequest<S5BProxyRequest>,SignalConnection>(); + + private Logger logger_ = Logger.getLogger(this.getClass().getName()); public SOCKS5BytestreamProxyFinder(final JID service, IQRouter iqRouter) { @@ -57,27 +70,42 @@ public class SOCKS5BytestreamProxyFinder { handleServiceFound(j, d); } }); + onWalkCompleteConnection = serviceWalker.onWalkComplete.connect(new Slot() { + + @Override + public void call() { + handleWalkEnded(); + } + + }); serviceWalker.beginWalk(); } public void stop() { - serviceWalker.endWalk(); + for (SignalConnection onResponseConnection : requestOnResponseConnections.values()) { + onResponseConnection.disconnect(); + } + requestOnResponseConnections.clear(); + serviceWalker.endWalk(); onServiceFoundConnection.disconnect(); + onWalkCompleteConnection.disconnect(); serviceWalker = null; } - - public final Signal1<S5BProxyRequest> onProxyFound = new Signal1<S5BProxyRequest>(); + + public final Signal1<List<S5BProxyRequest>> onProxiesFound = new Signal1<List<S5BProxyRequest>>(); private void sendBytestreamQuery(final JID jid) { S5BProxyRequest proxyRequest = new S5BProxyRequest(); - GenericRequest<S5BProxyRequest> request = new GenericRequest<S5BProxyRequest>(IQ.Type.Get, jid, proxyRequest, iqRouter); - request.onResponse.connect(new Slot2<S5BProxyRequest, ErrorPayload>() { + final GenericRequest<S5BProxyRequest> requester = new GenericRequest<S5BProxyRequest>(IQ.Type.Get, jid, proxyRequest, iqRouter); + SignalConnection requestOnResponseConnection = requester.onResponse.connect(new Slot2<S5BProxyRequest, ErrorPayload>() { @Override public void call(S5BProxyRequest s, ErrorPayload e) { - handleProxyResponse(s, e); + handleProxyResponse(requester,s,e); } }); - request.send(); + pendingRequests.add(requester); + requestOnResponseConnections.put(requester, requestOnResponseConnection); + requester.send(); } private void handleServiceFound(final JID jid, DiscoInfo discoInfo) { @@ -85,15 +113,29 @@ public class SOCKS5BytestreamProxyFinder { sendBytestreamQuery(jid); } } - private void handleProxyResponse(S5BProxyRequest request, ErrorPayload error) { - if (error != null) { + + private void handleWalkEnded() { + if (pendingRequests.isEmpty()) { + onProxiesFound.emit(proxyHosts); + } + } + + private void handleProxyResponse(GenericRequest<S5BProxyRequest> requester,S5BProxyRequest request, ErrorPayload error) { + SignalConnection requestOnResponseConnection = requestOnResponseConnections.remove(request); + if (requestOnResponseConnection != null) { + requestOnResponseConnection.disconnect(); + } + pendingRequests.remove(requester); + if (error != null) { logger_.fine("ERROR\n"); } else { if (request != null) { - onProxyFound.emit(request); - } else { - //assert(false); - } + logger_.fine("add request\n"); + proxyHosts.add(request); + } } + if (pendingRequests.isEmpty() && !serviceWalker.isActive()) { + onProxiesFound.emit(proxyHosts); + } } }
\ No newline at end of file |