summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTarun Gupta <tarun1995gupta@gmail.com>2015-08-03 12:08:37 (GMT)
committerAlex Clayton <alex.clayton@isode.com>2016-01-21 10:47:51 (GMT)
commit97a085f7e2c9b7820000eaace97dc0ab6392cb0d (patch)
treed3df191a053a69bc52238b76b8e9e42af043302c /src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java
parentfa1633e3b4d75a8217459cdc5fe64e9ee5ace65a (diff)
downloadstroke-97a085f7e2c9b7820000eaace97dc0ab6392cb0d.zip
stroke-97a085f7e2c9b7820000eaace97dc0ab6392cb0d.tar.bz2
Completes FileTransfer according to Swiften.
S5BTransport Session still needs generic T. FileTransfer, OutgoingFileTransfer and IncomingFileTransfer are made an interface due to the need of multiple inheritance in IncomingJingleFileTransfer and OutgoingJingleFileTransfer. Corresponding documentation has been updated. License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details. Test-Information: None. Change-Id: If44cf387767865c37492d871c12d623f94ebaa3a
Diffstat (limited to 'src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java')
-rw-r--r--src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java308
1 files changed, 308 insertions, 0 deletions
diff --git a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java
new file mode 100644
index 0000000..729193a
--- /dev/null
+++ b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2012-2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+/*
+ * Copyright (c) 2011 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt 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.signals.Slot1;
+import com.isode.stroke.signals.Signal1;
+import com.isode.stroke.signals.SignalConnection;
+import com.isode.stroke.network.ConnectionServer;
+import com.isode.stroke.network.ConnectionServerFactory;
+import com.isode.stroke.network.NATTraverser;
+import com.isode.stroke.network.NetworkInterface;
+import com.isode.stroke.network.NATPortMapping;
+import com.isode.stroke.network.NetworkEnvironment;
+import com.isode.stroke.network.NATTraversalGetPublicIPRequest;
+import com.isode.stroke.network.NATTraversalForwardPortRequest;
+import com.isode.stroke.network.NATTraversalRemovePortForwardingRequest;
+import com.isode.stroke.network.HostAddress;
+import com.isode.stroke.network.HostAddressPort;
+import java.util.Vector;
+import java.util.logging.Logger;
+
+public class SOCKS5BytestreamServerManager {
+
+ public static final int LISTEN_PORTS_BEGIN = 10000;
+ public static final int LISTEN_PORTS_END = 11000;
+
+ private SOCKS5BytestreamRegistry bytestreamRegistry;
+ private ConnectionServerFactory connectionServerFactory;
+ private NetworkEnvironment networkEnvironment;
+ private NATTraverser natTraverser;
+ private enum State { Start, Initializing, Initialized };
+ private State state;
+ private SOCKS5BytestreamServer server;
+ private ConnectionServer connectionServer;
+ private int connectionServerPort;
+
+ private NATTraversalGetPublicIPRequest getPublicIPRequest;
+ private NATTraversalForwardPortRequest forwardPortRequest;
+ private NATTraversalRemovePortForwardingRequest unforwardPortRequest;
+ private HostAddress publicAddress;
+ private NATPortMapping portMapping;
+ private boolean attemptedPortMapping_;
+
+ private SOCKS5BytestreamServerResourceUser s5bServerResourceUser_;
+ private SOCKS5BytestreamServerPortForwardingUser s5bServerPortForwardingUser_;
+ private Logger logger_ = Logger.getLogger(this.getClass().getName());
+
+ public SOCKS5BytestreamServerManager(SOCKS5BytestreamRegistry bytestreamRegistry, ConnectionServerFactory connectionServerFactory, NetworkEnvironment networkEnvironment, NATTraverser natTraverser) {
+ this.bytestreamRegistry = bytestreamRegistry;
+ this.connectionServerFactory = connectionServerFactory;
+ this.networkEnvironment = networkEnvironment;
+ this.natTraverser = natTraverser;
+ this.state = State.Start;
+ this.server = null;
+ this.attemptedPortMapping_ = false;
+ }
+
+ /**
+ * User should call delete to free the resources.
+ */
+ public void delete() {
+ //SWIFT_LOG_ASSERT(!connectionServer, warning) << std::endl;
+ //SWIFT_LOG_ASSERT(!getPublicIPRequest, warning) << std::endl;
+ //SWIFT_LOG_ASSERT(!forwardPortRequest, warning) << std::endl;
+ //SWIFT_LOG_ASSERT(state == Start, warning) << std::endl;
+ if (portMapping != null && unforwardPortRequest == null) {
+ //SWIFT_LOG(warning) << "Port forwarding still alive. Trying to remove it now." << std::endl;
+ unforwardPortRequest = natTraverser.createRemovePortForwardingRequest(portMapping.getLocalPort(), portMapping.getPublicPort());
+ unforwardPortRequest.start();
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ try {
+ delete();
+ }
+ finally {
+ super.finalize();
+ }
+ }
+
+ public SOCKS5BytestreamServerResourceUser aquireResourceUser() {
+ SOCKS5BytestreamServerResourceUser resourceUser = null;
+ if (s5bServerResourceUser_ == null) {
+ resourceUser = new SOCKS5BytestreamServerResourceUser(this);
+ s5bServerResourceUser_ = resourceUser;
+ }
+ else {
+ resourceUser = s5bServerResourceUser_;
+ }
+ return resourceUser;
+ }
+
+ public SOCKS5BytestreamServerPortForwardingUser aquirePortForwardingUser() {
+ SOCKS5BytestreamServerPortForwardingUser portForwardingUser = null;
+ if (s5bServerPortForwardingUser_ == null) {
+ portForwardingUser = new SOCKS5BytestreamServerPortForwardingUser(this);
+ s5bServerPortForwardingUser_ = portForwardingUser;
+ }
+ else {
+ portForwardingUser = s5bServerPortForwardingUser_;
+ }
+ return portForwardingUser;
+ }
+
+ public void stop() {
+ if (getPublicIPRequest != null) {
+ getPublicIPRequest.stop();
+ getPublicIPRequest = null;
+ }
+ if (forwardPortRequest != null) {
+ forwardPortRequest.stop();
+ forwardPortRequest = null;
+ }
+ if (server != null) {
+ server.stop();
+ server = null;
+ }
+ if (connectionServer != null) {
+ connectionServer.stop();
+ connectionServer = null;
+ }
+
+ state = State.Start;
+ }
+
+ public Vector<HostAddressPort> getHostAddressPorts() {
+ Vector<HostAddressPort> result = new Vector<HostAddressPort>();
+ if (connectionServer != null) {
+ Vector<NetworkInterface> networkInterfaces = networkEnvironment.getNetworkInterfaces();
+ for (final NetworkInterface networkInterface : networkInterfaces) {
+ for (final HostAddress address : networkInterface.getAddresses()) {
+ result.add(new HostAddressPort(address, connectionServerPort));
+ }
+ }
+ }
+ return result;
+ }
+
+ public Vector<HostAddressPort> getAssistedHostAddressPorts() {
+ Vector<HostAddressPort> result = new Vector<HostAddressPort>();
+ if (publicAddress != null && portMapping != null) {
+ result.add(new HostAddressPort(publicAddress, portMapping.getPublicPort()));
+ }
+ return result;
+ }
+
+ public SOCKS5BytestreamServer getServer() {
+ return server;
+ }
+
+ boolean isInitialized() {
+ return State.Initialized.equals(state);
+ }
+
+ void initialize() {
+ if (State.Start.equals(state)) {
+ state = State.Initializing;
+
+ // Find a port to listen on
+ assert(connectionServer == null);
+ int port;
+ for (port = LISTEN_PORTS_BEGIN; port < LISTEN_PORTS_END; ++port) {
+ logger_.fine("Trying to start server on port " + port + "\n");
+ connectionServer = connectionServerFactory.createConnectionServer(new HostAddress("0.0.0.0"), port);
+ ConnectionServer.Error error = connectionServer.tryStart();
+ if (error == null) {
+ break;
+ }
+ else if (!ConnectionServer.Error.Conflict.equals(error)) {
+ logger_.fine("Error starting server\n");
+ onInitialized.emit(false);
+ return;
+ }
+ connectionServer = null;
+ }
+ if (connectionServer == null) {
+ logger_.fine("Unable to find an open port\n");
+ onInitialized.emit(false);
+ return;
+ }
+ logger_.fine("Server started succesfully\n");
+ connectionServerPort = port;
+
+ // Start bytestream server. Should actually happen before the connectionserver is started
+ // but that doesn't really matter here.
+ assert(server == null);
+ server = new SOCKS5BytestreamServer(connectionServer, bytestreamRegistry);
+ server.start();
+ checkInitializeFinished();
+ }
+ }
+
+ boolean isPortForwardingReady() {
+ return attemptedPortMapping_ && getPublicIPRequest == null && forwardPortRequest == null;
+ }
+
+ void setupPortForwarding() {
+ assert(server != null);
+ attemptedPortMapping_ = true;
+
+ // Retrieve public addresses
+ assert(getPublicIPRequest == null);
+ publicAddress = null;
+ if ((natTraverser.createGetPublicIPRequest() != null)) {
+ getPublicIPRequest = natTraverser.createGetPublicIPRequest();
+ getPublicIPRequest.onResult.connect(new Slot1<HostAddress>() {
+ @Override
+ public void call(HostAddress a) {
+ handleGetPublicIPResult(a);
+ }
+ });
+ getPublicIPRequest.start();
+ }
+
+ // Forward ports
+ int port = server.getAddressPort().getPort();
+ assert(forwardPortRequest == null);
+ portMapping = null;
+ if ((natTraverser.createForwardPortRequest(port, port) != null)) {
+ forwardPortRequest = natTraverser.createForwardPortRequest(port, port);
+ forwardPortRequest.onResult.connect(new Slot1<NATPortMapping>() {
+ @Override
+ public void call(NATPortMapping n) {
+ handleForwardPortResult(n);
+ }
+ });
+ forwardPortRequest.start();
+ }
+ }
+
+ void removePortForwarding() {
+ // remove port forwards
+ if (portMapping != null) {
+ unforwardPortRequest = natTraverser.createRemovePortForwardingRequest(portMapping.getLocalPort(), portMapping.getPublicPort());
+ unforwardPortRequest.onResult.connect(new Slot1<Boolean>() {
+ @Override
+ public void call(Boolean b) {
+ handleUnforwardPortResult(b);
+ }
+ });
+ unforwardPortRequest.start();
+ }
+ }
+
+ void checkInitializeFinished() {
+ assert(State.Initializing.equals(state));
+ state = State.Initialized;
+ onInitialized.emit(true);
+ }
+
+ void handleGetPublicIPResult(HostAddress address) {
+ if (address != null) {
+ logger_.fine("Public IP discovered as " + address.toString() + ".\n");
+ }
+ else {
+ logger_.fine("No public IP discoverable.\n");
+ }
+
+ publicAddress = address;
+
+ getPublicIPRequest.stop();
+ getPublicIPRequest = null;
+ }
+
+ void handleForwardPortResult(NATPortMapping mapping) {
+ if (mapping != null) {
+ logger_.fine("Mapping port was successful.\n");
+ }
+ else {
+ logger_.fine("Mapping port has failed.\n");
+ }
+
+ portMapping = mapping;
+ onPortForwardingSetup.emit(mapping != null);
+
+ forwardPortRequest.stop();
+ forwardPortRequest = null;
+ }
+
+ void handleUnforwardPortResult(Boolean result) {
+ if (result != null && result) {
+ portMapping = null;
+ }
+ else {
+ logger_.warning("Failed to remove port forwarding.\n");
+ }
+ attemptedPortMapping_ = false;
+ unforwardPortRequest = null;
+ }
+
+ Signal1<Boolean/* success */> onInitialized = new Signal1<Boolean>();
+ Signal1<Boolean/* success */> onPortForwardingSetup = new Signal1<Boolean>();
+} \ No newline at end of file