1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-01 06:05:24 +02:00

Increase ssh default timeout, support ssh proxy options and add tracing support

This commit is contained in:
Martin Oberhuber 2006-05-19 16:08:48 +00:00
parent 57a32aa51a
commit 5e65fc8836
4 changed files with 159 additions and 34 deletions

View file

@ -10,6 +10,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.rse.services.ssh, org.eclipse.rse.services.ssh,
org.eclipse.rse.services, org.eclipse.rse.services,
org.eclipse.rse.ui, org.eclipse.rse.ui,
org.eclipse.team.cvs.core;bundle-version="[3.2.0,4.0.0)",
org.eclipse.team.cvs.ssh2;bundle-version="[3.2.0,4.0.0)", org.eclipse.team.cvs.ssh2;bundle-version="[3.2.0,4.0.0)",
org.eclipse.team.cvs.ui;bundle-version="[3.2.0,4.0.0)", org.eclipse.team.cvs.ui;bundle-version="[3.2.0,4.0.0)",
org.eclipse.ui, org.eclipse.ui,

View file

@ -1,5 +1,10 @@
package org.eclipse.rse.connectorservice.ssh; package org.eclipse.rse.connectorservice.ssh;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin; import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext; import org.osgi.framework.BundleContext;
@ -14,7 +19,7 @@ public class Activator extends AbstractUIPlugin {
// The shared instance // The shared instance
private static Activator plugin; private static Activator plugin;
/** /**
* The constructor * The constructor
*/ */
@ -48,6 +53,37 @@ public class Activator extends AbstractUIPlugin {
return plugin; return plugin;
} }
private static Boolean fTracingOn = null;
public static boolean isTracingOn() {
if (fTracingOn==null) {
String id = plugin.getBundle().getSymbolicName();
String val = Platform.getDebugOption(id + "/debug"); //$NON-NLS-1$
if ("true".equals(val)) {
fTracingOn = Boolean.TRUE;
} else {
fTracingOn = Boolean.FALSE;
}
}
return fTracingOn.booleanValue();
}
public static String getTimestamp() {
try {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //$NON-NLS-1$
return formatter.format(new Date());
} catch (Exception e) {
// If there were problems writing out the date, ignore and
// continue since that shouldn't stop us from logging the rest
// of the information
}
return Long.toString(System.currentTimeMillis());
}
public static void trace(String msg) {
if (isTracingOn()) {
String fullMsg = getTimestamp() + " | " + Thread.currentThread().getName() + " | " + msg;
System.out.println(fullMsg);
}
}
/** /**
* Returns an image descriptor for the image file at the given * Returns an image descriptor for the image file at the given
* plug-in relative path. * plug-in relative path.

View file

@ -11,7 +11,14 @@
package org.eclipse.rse.connectorservice.ssh; package org.eclipse.rse.connectorservice.ssh;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IPreferenceStore;
@ -19,12 +26,19 @@ import org.eclipse.rse.core.subsystems.AbstractConnectorService;
import org.eclipse.rse.model.IHost; import org.eclipse.rse.model.IHost;
import org.eclipse.rse.services.ssh.ISshSessionProvider; import org.eclipse.rse.services.ssh.ISshSessionProvider;
import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Display;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.core.util.Util;
import org.eclipse.team.internal.ccvs.ssh2.CVSSSH2Plugin; import org.eclipse.team.internal.ccvs.ssh2.CVSSSH2Plugin;
import org.eclipse.team.internal.ccvs.ssh2.ISSHContants; import org.eclipse.team.internal.ccvs.ssh2.ISSHContants;
import org.eclipse.team.internal.ccvs.ui.UserValidationDialog; import org.eclipse.team.internal.ccvs.ui.UserValidationDialog;
import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Proxy;
import com.jcraft.jsch.ProxyHTTP;
import com.jcraft.jsch.ProxySOCKS5;
import com.jcraft.jsch.Session; import com.jcraft.jsch.Session;
import com.jcraft.jsch.SocketFactory;
import com.jcraft.jsch.UserInfo; import com.jcraft.jsch.UserInfo;
/** /**
@ -35,7 +49,6 @@ public class SshConnectorService extends AbstractConnectorService implements ISs
private static final int SSH_DEFAULT_PORT = 22; private static final int SSH_DEFAULT_PORT = 22;
private static JSch jsch=new JSch(); private static JSch jsch=new JSch();
private Session session; private Session session;
// protected SftpFileService _sftpFileService;
public SshConnectorService(IHost host) { public SshConnectorService(IHost host) {
//TODO the port parameter doesnt really make sense here since //TODO the port parameter doesnt really make sense here since
@ -43,7 +56,6 @@ public class SshConnectorService extends AbstractConnectorService implements ISs
//setPort() on our base class -- I assume the port is meant to //setPort() on our base class -- I assume the port is meant to
//be a local port. //be a local port.
super("SSH Connector Service", "SSH Connector Service Description", host, 0); super("SSH Connector Service", "SSH Connector Service Description", host, 0);
// _sftpFileService = new SftpFileService(this);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -51,6 +63,13 @@ public class SshConnectorService extends AbstractConnectorService implements ISs
//---------------------------------------------------------------------- //----------------------------------------------------------------------
private static String current_ssh_home = null; private static String current_ssh_home = null;
private static String current_pkeys = ""; //$NON-NLS-1$ private static String current_pkeys = ""; //$NON-NLS-1$
protected static int getSshTimeoutInMillis() {
//return CVSProviderPlugin.getPlugin().getTimeout() * 1000;
// TODO Hard-code the timeout for now since Jsch doesn't respect CVS timeout
// See bug 92887
return 60000;
}
static String SSH_HOME_DEFAULT = null; static String SSH_HOME_DEFAULT = null;
static { static {
@ -66,6 +85,8 @@ public class SshConnectorService extends AbstractConnectorService implements ISs
} }
} }
// Load ssh prefs from Team/CVS for now.
// TODO do our own preference page.
static void loadSshPrefs() static void loadSshPrefs()
{ {
IPreferenceStore store = CVSSSH2Plugin.getDefault().getPreferenceStore(); IPreferenceStore store = CVSSSH2Plugin.getDefault().getPreferenceStore();
@ -122,6 +143,79 @@ public class SshConnectorService extends AbstractConnectorService implements ISs
} catch (Exception e) { } catch (Exception e) {
} }
} }
static Proxy loadSshProxyPrefs() {
boolean useProxy = CVSProviderPlugin.getPlugin().isUseProxy();
Proxy proxy = null;
if (useProxy) {
String _type = CVSProviderPlugin.getPlugin().getProxyType();
String _host = CVSProviderPlugin.getPlugin().getProxyHost();
String _port = CVSProviderPlugin.getPlugin().getProxyPort();
boolean useAuth = CVSProviderPlugin.getPlugin().isUseProxyAuth();
String _user = ""; //$NON-NLS-1$
String _pass = ""; //$NON-NLS-1$
// Retrieve username and password from keyring.
if(useAuth){
_user=CVSProviderPlugin.getPlugin().getProxyUser();
_pass=CVSProviderPlugin.getPlugin().getProxyPassword();
}
String proxyhost = _host + ":" + _port; //$NON-NLS-1$
if (_type.equals(CVSProviderPlugin.PROXY_TYPE_HTTP)) {
proxy = new ProxyHTTP(proxyhost);
if (useAuth) {
((ProxyHTTP) proxy).setUserPasswd(_user, _pass);
}
} else if (_type.equals(CVSProviderPlugin.PROXY_TYPE_SOCKS5)) {
proxy = new ProxySOCKS5(proxyhost);
if (useAuth) {
((ProxySOCKS5) proxy).setUserPasswd(_user, _pass);
}
} else {
proxy = null;
}
}
return proxy;
}
public static class SimpleSocketFactory implements SocketFactory {
InputStream in = null;
OutputStream out = null;
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
Socket socket = null;
socket = new Socket(host, port);
return socket;
}
public InputStream getInputStream(Socket socket) throws IOException {
if (in == null)
in = socket.getInputStream();
return in;
}
public OutputStream getOutputStream(Socket socket) throws IOException {
if (out == null)
out = socket.getOutputStream();
return out;
}
}
public static class ResponsiveSocketFacory extends SimpleSocketFactory {
private IProgressMonitor monitor;
public ResponsiveSocketFacory(IProgressMonitor monitor) {
this.monitor = monitor;
}
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
Socket socket = null;
socket = Util.createSocket(host, port, monitor);
// Null out the monitor so we don't hold onto anything
// (i.e. the SSH2 session will keep a handle to the socket factory around
monitor = new NullProgressMonitor();
// Set the socket timeout
socket.setSoTimeout(getSshTimeoutInMillis());
return socket;
}
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// </copied from org.eclipse.team.cvs.ssh2> // </copied from org.eclipse.team.cvs.ssh2>
@ -138,32 +232,29 @@ public class SshConnectorService extends AbstractConnectorService implements ISs
String host = getHostName(); String host = getHostName();
String user = getUserId(); String user = getUserId();
Proxy proxy = loadSshProxyPrefs();
session=jsch.getSession(user, host, SSH_DEFAULT_PORT); session=jsch.getSession(user, host, SSH_DEFAULT_PORT);
if (proxy != null) {
session.setProxy(proxy);
}
session.setTimeout(getSshTimeoutInMillis());
session.setPassword(getPasswordInformation().getPassword()); session.setPassword(getPasswordInformation().getPassword());
//session.setPassword("your password"); session.setUserInfo(new MyUserInfo(user));
session.setSocketFactory(new ResponsiveSocketFacory(monitor));
// username and password will be given via UserInfo interface.
UserInfo ui=new MyUserInfo(user);
session.setUserInfo(ui);
//java.util.Hashtable config=new java.util.Hashtable(); //java.util.Hashtable config=new java.util.Hashtable();
//config.put("StrictHostKeyChecking", "no"); //config.put("StrictHostKeyChecking", "no");
//session.setConfig(config); //session.setConfig(config);
session.connect(3000); // making connection with timeout. try {
Activator.trace("connecting..."); //$NON-NLS-1$
//now also connect the sftpFileService. It's not very nice to force session.connect();
//the connector service know about the file service, and connect it Activator.trace("connected"); //$NON-NLS-1$
//so early -- lazy connect inside the sftpFileService would be better. } catch (JSchException e) {
//But the FileServiceSubsystem only calls internalConnect() on the Activator.trace("connect failed: "+e.toString()); //$NON-NLS-1$
//connector service, and doesn't try to connect the file service if (session.isConnected())
//individually. session.disconnect();
//TODO: From the API point of view, it might be better if the file throw e;
//service had a connect() method and could decide itself if and how }
//it wants to use the connector service.
//Or could we ensure that the FileService is instanciated only once
//it needs to be connected? - Currently this is not the case (it is
//instanciated very early by the subsystem).
// _sftpFileService.connect();
} }
public void internalDisconnect(IProgressMonitor monitor) public void internalDisconnect(IProgressMonitor monitor)
@ -171,7 +262,8 @@ public class SshConnectorService extends AbstractConnectorService implements ISs
//TODO: Check, Is disconnect being called because the network (connection) went down? //TODO: Check, Is disconnect being called because the network (connection) went down?
//TODO: Fire communication event (aboutToDisconnect) -- see DStoreConnectorService.internalDisconnect() //TODO: Fire communication event (aboutToDisconnect) -- see DStoreConnectorService.internalDisconnect()
//TODO: Wrap exception in an InvocationTargetException -- see DStoreConnectorService.internalDisconnect() //TODO: Wrap exception in an InvocationTargetException -- see DStoreConnectorService.internalDisconnect()
// _sftpFileService.disconnect(); //Will services like the sftp service be disconnected too? Or notified?
Activator.trace("disconnect"); //$NON-NLS-1$
session.disconnect(); session.disconnect();
} }
@ -182,11 +274,6 @@ public class SshConnectorService extends AbstractConnectorService implements ISs
public Session getSession() { public Session getSession() {
return session; return session;
} }
/*
public IFileService getFileService() {
return _sftpFileService;
}
*/
private static Display getStandardDisplay() { private static Display getStandardDisplay() {
Display display = Display.getCurrent(); Display display = Display.getCurrent();

View file

@ -71,7 +71,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
fUserHome = fChannelSftp.pwd(); fUserHome = fChannelSftp.pwd();
Activator.trace("SftpFileService.connected"); //$NON-NLS-1$ Activator.trace("SftpFileService.connected"); //$NON-NLS-1$
} catch(Exception e) { } catch(Exception e) {
Activator.trace("SftpFileService.connecting failed: "+e.toString()); Activator.trace("SftpFileService.connecting failed: "+e.toString()); //$NON-NLS-1$
throw e; throw e;
} }
} }
@ -79,7 +79,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
protected ChannelSftp getChannel(String task) { protected ChannelSftp getChannel(String task) {
Activator.trace(task); Activator.trace(task);
if (fChannelSftp==null || !fChannelSftp.isConnected()) { if (fChannelSftp==null || !fChannelSftp.isConnected()) {
Activator.trace(task + ": channel not connected: "+fChannelSftp); Activator.trace(task + ": channel not connected: "+fChannelSftp); //$NON-NLS-1$
} }
return fChannelSftp; return fChannelSftp;
} }
@ -98,9 +98,9 @@ public class SftpFileService extends AbstractFileService implements IFileService
SftpATTRS attrs = null; SftpATTRS attrs = null;
try { try {
attrs = getChannel("SftpFileService.getFile").stat(remoteParent+'/'+fileName); //$NON-NLS-1$ attrs = getChannel("SftpFileService.getFile").stat(remoteParent+'/'+fileName); //$NON-NLS-1$
Activator.trace("SftpFileService.getFile done"); Activator.trace("SftpFileService.getFile done"); //$NON-NLS-1$
} catch(Exception e) { } catch(Exception e) {
Activator.trace("SftpFileService.getFile failed: "+e.toString()); Activator.trace("SftpFileService.getFile failed: "+e.toString()); //$NON-NLS-1$
} }
if (attrs!=null) { if (attrs!=null) {
node = makeHostFile(remoteParent, fileName, attrs); node = makeHostFile(remoteParent, fileName, attrs);
@ -141,13 +141,14 @@ public class SftpFileService extends AbstractFileService implements IFileService
} }
} }
} }
Activator.trace("SftpFileService.internalFetch ok"); //$NON-NLS-1$
} catch(Exception e) { } catch(Exception e) {
//TODO throw new SystemMessageException. //TODO throw new SystemMessageException.
//We get a "2: No such file" exception when we try to get contents //We get a "2: No such file" exception when we try to get contents
//of a symbolic link that turns out to point to a file rather than //of a symbolic link that turns out to point to a file rather than
//a directory. In this case, the result is probably expected. //a directory. In this case, the result is probably expected.
//We should try to classify symbolic links as "file" or "dir" correctly. //We should try to classify symbolic links as "file" or "dir" correctly.
Activator.trace("SftpFileService.internalFetch failed: "+e.toString()); Activator.trace("SftpFileService.internalFetch failed: "+e.toString()); //$NON-NLS-1$
e.printStackTrace(); e.printStackTrace();
} }
return (IHostFile[])results.toArray(new IHostFile[results.size()]); return (IHostFile[])results.toArray(new IHostFile[results.size()]);