mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-16 12:45:41 +02:00
Support proxy connection for gateway without sftp or with MaxSession=1
Command proxy does not work if both the host and the gateway have MaxSession=1 (caused by 356657). Add support in JschConnection for a connection which has a session but isn't fully setup. Such a connection isn't considered open. And if it is opened after it already has a session without setupFully=false (default), then all setup setups are done. Also change that getProxyConnection returns null not a LocalConnection for a local command. This reduces the dependency on LocalConnection from within jsch.core.*. Change-Id: I64d05e69749d96248d2f40bd2db021d809cb04a9
This commit is contained in:
parent
b1903767f3
commit
95db103e5b
5 changed files with 106 additions and 57 deletions
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
org.eclipse.jdt.core.compiler.source=1.6
|
org.eclipse.jdt.core.compiler.source=1.7
|
||||||
|
|
|
@ -15,4 +15,4 @@ Bundle-ActivationPolicy: lazy
|
||||||
Export-Package: org.eclipse.remote.internal.jsch.core;x-friends:="org.eclipse.remote.jsch.ui",
|
Export-Package: org.eclipse.remote.internal.jsch.core;x-friends:="org.eclipse.remote.jsch.ui",
|
||||||
org.eclipse.remote.internal.jsch.core.messages;x-internal:=true
|
org.eclipse.remote.internal.jsch.core.messages;x-internal:=true
|
||||||
Bundle-Localization: plugin
|
Bundle-Localization: plugin
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||||
|
|
|
@ -27,14 +27,12 @@ import org.eclipse.osgi.util.NLS;
|
||||||
import org.eclipse.remote.core.IRemoteConnection;
|
import org.eclipse.remote.core.IRemoteConnection;
|
||||||
import org.eclipse.remote.core.IRemoteConnectionChangeEvent;
|
import org.eclipse.remote.core.IRemoteConnectionChangeEvent;
|
||||||
import org.eclipse.remote.core.IRemoteConnectionChangeListener;
|
import org.eclipse.remote.core.IRemoteConnectionChangeListener;
|
||||||
import org.eclipse.remote.core.IRemoteConnectionManager;
|
|
||||||
import org.eclipse.remote.core.IRemoteConnectionWorkingCopy;
|
import org.eclipse.remote.core.IRemoteConnectionWorkingCopy;
|
||||||
import org.eclipse.remote.core.IRemoteFileManager;
|
import org.eclipse.remote.core.IRemoteFileManager;
|
||||||
import org.eclipse.remote.core.IRemoteProcess;
|
import org.eclipse.remote.core.IRemoteProcess;
|
||||||
import org.eclipse.remote.core.IRemoteProcessBuilder;
|
import org.eclipse.remote.core.IRemoteProcessBuilder;
|
||||||
import org.eclipse.remote.core.IRemoteServices;
|
import org.eclipse.remote.core.IRemoteServices;
|
||||||
import org.eclipse.remote.core.IUserAuthenticator;
|
import org.eclipse.remote.core.IUserAuthenticator;
|
||||||
import org.eclipse.remote.core.RemoteServices;
|
|
||||||
import org.eclipse.remote.core.exception.AddressInUseException;
|
import org.eclipse.remote.core.exception.AddressInUseException;
|
||||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||||
import org.eclipse.remote.core.exception.UnableToForwardPortException;
|
import org.eclipse.remote.core.exception.UnableToForwardPortException;
|
||||||
|
@ -186,6 +184,7 @@ public class JSchConnection implements IRemoteConnection {
|
||||||
private final List<Session> fSessions = new ArrayList<Session>();
|
private final List<Session> fSessions = new ArrayList<Session>();
|
||||||
|
|
||||||
private ChannelSftp fSftpChannel;
|
private ChannelSftp fSftpChannel;
|
||||||
|
private boolean isFullySetup; // including sftp channel and environment
|
||||||
|
|
||||||
public JSchConnection(String name, IRemoteServices services) {
|
public JSchConnection(String name, IRemoteServices services) {
|
||||||
fRemoteServices = services;
|
fRemoteServices = services;
|
||||||
|
@ -590,23 +589,22 @@ public class JSchConnection implements IRemoteConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the proxy connection. If no proxy is used it returns a local connection.
|
* Gets the proxy connection. If no proxy connection is used it returns null.
|
||||||
*
|
*
|
||||||
* @return proxy connection
|
* @return proxy connection
|
||||||
*/
|
*/
|
||||||
public IRemoteConnection getProxyConnection() {
|
public JSchConnection getProxyConnection() {
|
||||||
String proxyConnectionName = getProxyConnectionName();
|
String proxyConnectionName = getProxyConnectionName();
|
||||||
if (proxyConnectionName.equals(EMPTY_STRING)) {
|
if (proxyConnectionName.equals(EMPTY_STRING)) {
|
||||||
return RemoteServices.getLocalServices().getConnectionManager().getConnection(
|
return null;
|
||||||
IRemoteConnectionManager.LOCAL_CONNECTION_NAME);
|
|
||||||
}
|
}
|
||||||
return fManager.getConnection(proxyConnectionName);
|
return (JSchConnection) fManager.getConnection(proxyConnectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the proxy connection name
|
* Gets the proxy connection name
|
||||||
*
|
*
|
||||||
* @return proxy connection name
|
* @return proxy connection name. If no proxy is used returns an empty string. Never returns null.
|
||||||
*/
|
*/
|
||||||
public String getProxyConnectionName() {
|
public String getProxyConnectionName() {
|
||||||
return fAttributes.getAttribute(JSchConnectionAttributes.PROXYCONNECTION_ATTR, EMPTY_STRING);
|
return fAttributes.getAttribute(JSchConnectionAttributes.PROXYCONNECTION_ATTR, EMPTY_STRING);
|
||||||
|
@ -699,6 +697,24 @@ public class JSchConnection implements IRemoteConnection {
|
||||||
return fWorkingDir;
|
return fWorkingDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the connection has a valid open session. Doesn't check whether the connection is fully setup.
|
||||||
|
*
|
||||||
|
* @return true if a valid session is available.
|
||||||
|
*/
|
||||||
|
public boolean hasOpenSession() {
|
||||||
|
boolean hasOpenSession = fSessions.size() > 0;
|
||||||
|
if (hasOpenSession) {
|
||||||
|
for (Session session : fSessions) {
|
||||||
|
hasOpenSession &= session.isConnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasOpenSession) {
|
||||||
|
close(); // Cleanup if session is closed
|
||||||
|
}
|
||||||
|
return hasOpenSession;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
|
@ -706,16 +722,7 @@ public class JSchConnection implements IRemoteConnection {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isOpen() {
|
public boolean isOpen() {
|
||||||
boolean isOpen = fSessions.size() > 0;
|
return hasOpenSession() && isFullySetup;
|
||||||
if (isOpen) {
|
|
||||||
for (Session session : fSessions) {
|
|
||||||
isOpen &= session.isConnected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isOpen) {
|
|
||||||
close(); // Cleanup if session is closed
|
|
||||||
}
|
|
||||||
return isOpen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPasswordAuth() {
|
public boolean isPasswordAuth() {
|
||||||
|
@ -869,16 +876,44 @@ public class JSchConnection implements IRemoteConnection {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void open(IProgressMonitor monitor) throws RemoteConnectionException {
|
public void open(IProgressMonitor monitor) throws RemoteConnectionException {
|
||||||
if (!isOpen()) {
|
open(monitor, true);
|
||||||
checkIsConfigured();
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open ssh connection without full setup (environment, sftp)
|
||||||
|
*
|
||||||
|
* @see org.eclipse.remote.core.IRemoteConnection#open()
|
||||||
|
*
|
||||||
|
* @param monitor
|
||||||
|
* @throws RemoteConnectionException
|
||||||
|
*/
|
||||||
|
public void openMinimal(IProgressMonitor monitor) throws RemoteConnectionException {
|
||||||
|
open(monitor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.remote.core.IRemoteConnection#open()
|
||||||
|
*
|
||||||
|
* @param monitor
|
||||||
|
* @param setupFully
|
||||||
|
* open a full featured connection (environment query and sftp)
|
||||||
|
* @throws RemoteConnectionException
|
||||||
|
*/
|
||||||
|
private void open(IProgressMonitor monitor, boolean setupFully) throws RemoteConnectionException {
|
||||||
SubMonitor subMon = SubMonitor.convert(monitor, 60);
|
SubMonitor subMon = SubMonitor.convert(monitor, 60);
|
||||||
Session session = newSession(fManager.getUserAuthenticator(this), subMon.newChild(10));
|
if (!hasOpenSession()) {
|
||||||
|
checkIsConfigured();
|
||||||
|
newSession(fManager.getUserAuthenticator(this), subMon.newChild(10));
|
||||||
if (subMon.isCanceled()) {
|
if (subMon.isCanceled()) {
|
||||||
throw new RemoteConnectionException(Messages.JSchConnection_Connection_was_cancelled);
|
throw new RemoteConnectionException(Messages.JSchConnection_Connection_was_cancelled);
|
||||||
}
|
}
|
||||||
|
isFullySetup = false;
|
||||||
|
}
|
||||||
|
if (setupFully && !isFullySetup) { // happens on the first open with setupFully==true, which might not be the first open
|
||||||
|
isFullySetup = true;
|
||||||
// getCwd checks the exec channel before checkConfiguration checks the sftp channel
|
// getCwd checks the exec channel before checkConfiguration checks the sftp channel
|
||||||
fWorkingDir = getCwd(subMon.newChild(10));
|
fWorkingDir = getCwd(subMon.newChild(10));
|
||||||
if (!checkConfiguration(session, subMon.newChild(20))) {
|
if (!checkConfiguration(fSessions.get(0), subMon.newChild(20))) {
|
||||||
newSession(fManager.getUserAuthenticator(this), subMon.newChild(10));
|
newSession(fManager.getUserAuthenticator(this), subMon.newChild(10));
|
||||||
loadEnv(subMon.newChild(10));
|
loadEnv(subMon.newChild(10));
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,15 @@ import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.core.runtime.SubMonitor;
|
import org.eclipse.core.runtime.SubMonitor;
|
||||||
import org.eclipse.remote.core.IRemoteConnection;
|
import org.eclipse.remote.core.IRemoteConnectionManager;
|
||||||
import org.eclipse.remote.core.IRemoteProcess;
|
import org.eclipse.remote.core.IRemoteProcess;
|
||||||
import org.eclipse.remote.core.IRemoteProcessBuilder;
|
import org.eclipse.remote.core.RemoteServices;
|
||||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||||
import org.eclipse.remote.internal.jsch.core.messages.Messages;
|
import org.eclipse.remote.internal.jsch.core.messages.Messages;
|
||||||
|
|
||||||
import com.jcraft.jsch.Channel;
|
import com.jcraft.jsch.Channel;
|
||||||
|
import com.jcraft.jsch.ChannelExec;
|
||||||
|
import com.jcraft.jsch.JSchException;
|
||||||
import com.jcraft.jsch.Proxy;
|
import com.jcraft.jsch.Proxy;
|
||||||
import com.jcraft.jsch.SocketFactory;
|
import com.jcraft.jsch.SocketFactory;
|
||||||
|
|
||||||
|
@ -45,11 +47,12 @@ public class JSchConnectionProxyFactory {
|
||||||
private static class CommandProxy implements Proxy {
|
private static class CommandProxy implements Proxy {
|
||||||
private String command;
|
private String command;
|
||||||
private IRemoteProcess process;
|
private IRemoteProcess process;
|
||||||
private IRemoteConnection connection;
|
private JSchConnection connection;
|
||||||
private IProgressMonitor monitor;
|
private IProgressMonitor monitor;
|
||||||
|
private boolean connectCalled = false;
|
||||||
|
|
||||||
private CommandProxy(IRemoteConnection connection, String command, IProgressMonitor monitor) {
|
private CommandProxy(JSchConnection connection, String command, IProgressMonitor monitor) {
|
||||||
if (command == null || connection == null || monitor == null)
|
if (command == null || monitor == null)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
this.command = command;
|
this.command = command;
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
@ -74,33 +77,45 @@ public class JSchConnectionProxyFactory {
|
||||||
@Override
|
@Override
|
||||||
public void connect(SocketFactory socket_factory, String host,
|
public void connect(SocketFactory socket_factory, String host,
|
||||||
int port, int timeout) throws IOException {
|
int port, int timeout) throws IOException {
|
||||||
assert connection != null : "connect should only be called once"; //$NON-NLS-1$
|
assert !connectCalled : "connect should only be called once"; //$NON-NLS-1$
|
||||||
try {
|
try {
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
timeout = 10000; // default to 10s
|
timeout = 10000; // default to 10s
|
||||||
}
|
}
|
||||||
final int waitTime = 50;
|
final int waitTime = 50;
|
||||||
final int waitSteps = timeout / waitTime;
|
final int waitSteps = timeout / waitTime;
|
||||||
SubMonitor subMon;
|
SubMonitor subMon = SubMonitor.convert(monitor, waitSteps * 2);
|
||||||
|
final SubMonitor childMon = subMon.newChild(waitSteps);
|
||||||
|
|
||||||
// Open connection if it isn't already opened
|
// Open connection if it isn't already opened
|
||||||
if (!connection.isOpen()) {
|
|
||||||
subMon = SubMonitor.convert(monitor, waitSteps * 2);
|
|
||||||
try {
|
try {
|
||||||
connection.open(subMon.newChild(waitSteps));
|
if (connection != null) {
|
||||||
|
connection.openMinimal(childMon);
|
||||||
|
}
|
||||||
} catch (RemoteConnectionException e) {
|
} catch (RemoteConnectionException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
} else {
|
subMon.setWorkRemaining(waitSteps);
|
||||||
subMon = SubMonitor.convert(monitor, waitSteps);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start command
|
// Start command
|
||||||
command = command.replace("%h", host); //$NON-NLS-1$
|
command = command.replace("%h", host); //$NON-NLS-1$
|
||||||
command = command.replace("%p", Integer.toString(port)); //$NON-NLS-1$
|
command = command.replace("%p", Integer.toString(port)); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (connection != null) {
|
||||||
|
// The process-builder adds unnecessary extra commands (cd, export, ..) and might not work for restricted shells
|
||||||
|
try {
|
||||||
|
ChannelExec exec = connection.getExecChannel();
|
||||||
|
exec.setCommand(command);
|
||||||
|
exec.connect();
|
||||||
|
process = new JSchProcess(exec, false);
|
||||||
|
} catch (JSchException | RemoteConnectionException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
List<String> cmd = new ArgumentParser(command).getTokenList();
|
List<String> cmd = new ArgumentParser(command).getTokenList();
|
||||||
IRemoteProcessBuilder pb = connection.getProcessBuilder(cmd);
|
process = RemoteServices.getLocalServices().getConnectionManager().getConnection(
|
||||||
process = pb.start();
|
IRemoteConnectionManager.LOCAL_CONNECTION_NAME).getProcessBuilder(cmd).start();
|
||||||
|
}
|
||||||
|
|
||||||
// Wait on command to produce stdout output
|
// Wait on command to produce stdout output
|
||||||
long endTime = System.currentTimeMillis() + timeout;
|
long endTime = System.currentTimeMillis() + timeout;
|
||||||
|
@ -158,8 +173,7 @@ public class JSchConnectionProxyFactory {
|
||||||
};
|
};
|
||||||
}.start();
|
}.start();
|
||||||
} finally {
|
} finally {
|
||||||
// Not valid to call connect again or for any other command to access these variables. Setting to null to ensure.
|
connectCalled = true;
|
||||||
connection = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,11 +212,12 @@ public class JSchConnectionProxyFactory {
|
||||||
private Channel channel;
|
private Channel channel;
|
||||||
private JSchConnection connection;
|
private JSchConnection connection;
|
||||||
private IProgressMonitor monitor;
|
private IProgressMonitor monitor;
|
||||||
|
private boolean connectCalled = false;
|
||||||
|
|
||||||
private SSHForwardProxy(IRemoteConnection proxyConnection, IProgressMonitor monitor) {
|
private SSHForwardProxy(JSchConnection proxyConnection, IProgressMonitor monitor) {
|
||||||
if (proxyConnection == null || monitor == null)
|
if (proxyConnection == null || monitor == null)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
this.connection = (JSchConnection) proxyConnection; // only JSch supported for ForwardProxy
|
this.connection = proxyConnection;
|
||||||
this.monitor = monitor;
|
this.monitor = monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,19 +239,18 @@ public class JSchConnectionProxyFactory {
|
||||||
@Override
|
@Override
|
||||||
public void connect(SocketFactory socket_factory, String host, int port,
|
public void connect(SocketFactory socket_factory, String host, int port,
|
||||||
int timeout) throws Exception {
|
int timeout) throws Exception {
|
||||||
assert connection != null : "connect should only be called once"; //$NON-NLS-1$
|
assert !connectCalled : "connect should only be called once"; //$NON-NLS-1$
|
||||||
try {
|
try {
|
||||||
if (!connection.isOpen()) {
|
if (!connection.hasOpenSession()) {
|
||||||
try {
|
try {
|
||||||
connection.open(monitor);
|
connection.openMinimal(monitor);
|
||||||
} catch (RemoteConnectionException e) {
|
} catch (RemoteConnectionException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
channel = connection.getStreamForwarder(host, port);
|
channel = connection.getStreamForwarder(host, port);
|
||||||
} finally {
|
} finally {
|
||||||
// Not valid to call connect again or for any other command to access these variables. Setting to null to ensure.
|
connectCalled = true;
|
||||||
connection = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,14 +299,14 @@ public class JSchConnectionProxyFactory {
|
||||||
* Creates a (local or remote) command proxy.
|
* Creates a (local or remote) command proxy.
|
||||||
*
|
*
|
||||||
* @param connection
|
* @param connection
|
||||||
* Any (local or remote) connection. Cannot be null.
|
* Either a valid connection or null for a local command
|
||||||
* @param command
|
* @param command
|
||||||
* A valid proxy command. Cannot be null or empty.
|
* A valid proxy command. Cannot be null or empty.
|
||||||
* @param monitor
|
* @param monitor
|
||||||
* A valid progress monitor. Cannot be null.
|
* A valid progress monitor. Cannot be null.
|
||||||
* @return ssh proxy
|
* @return ssh proxy
|
||||||
*/
|
*/
|
||||||
public static Proxy createCommandProxy(IRemoteConnection connection, String command, IProgressMonitor monitor) {
|
public static Proxy createCommandProxy(JSchConnection connection, String command, IProgressMonitor monitor) {
|
||||||
return new CommandProxy(connection, command, monitor);
|
return new CommandProxy(connection, command, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +319,7 @@ public class JSchConnectionProxyFactory {
|
||||||
* A valid progress monitor. Cannot be null.
|
* A valid progress monitor. Cannot be null.
|
||||||
* @return ssh proxy
|
* @return ssh proxy
|
||||||
*/
|
*/
|
||||||
public static Proxy createForwardProxy(IRemoteConnection proxyConnection, IProgressMonitor monitor) {
|
public static Proxy createForwardProxy(JSchConnection proxyConnection, IProgressMonitor monitor) {
|
||||||
return new SSHForwardProxy(proxyConnection, monitor);
|
return new SSHForwardProxy(proxyConnection, monitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue