Browse Source

Yet another work-around for a Jsch bug: timeouts

Jsch 0.1.54 passes on the values from ~/.ssh/config for
"ServerAliveInterval" and "ConnectTimeout" as read from
the config file to java.net.Socket.setSoTimeout(). That
method expects milliseconds, but the values in the config
file are seconds!

The missing conversion in Jsch means that the timeout is
set way too low, and if the server doesn't respond within
that very short time frame, Jsch kills the connection and
then throws an exception with a message such as "session is
down" or "timeout in waiting for rekeying process".

As a work-around, do the conversion to milliseconds in the
Jsch-facing Config interface of OpenSshConfig. That way Jsch
already gets these values as milliseconds.

Bug: 526867
Change-Id: Ibc9b93f7722fffe10f3e770dfe7fdabfb3b97e74
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
stable-4.9
Thomas Wolf 7 years ago committed by Matthias Sohn
parent
commit
5284cc1bf7
  1. 3
      org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java
  2. 62
      org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java

3
org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java

@ -343,8 +343,7 @@ public class OpenSshConfigTest extends RepositoryTestCase {
assertEquals(h1.getConnectionAttempts(), h2.getConnectionAttempts()); assertEquals(h1.getConnectionAttempts(), h2.getConnectionAttempts());
final ConfigRepository.Config c = osc.getConfig("orcz"); final ConfigRepository.Config c = osc.getConfig("orcz");
assertNotNull(c); assertNotNull(c);
assertSame(c, h1.getConfig()); assertSame(h1.getConfig(), h2.getConfig());
assertSame(c, h2.getConfig());
} }
@Test @Test

62
org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java

@ -59,6 +59,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.errors.InvalidPatternException; import org.eclipse.jgit.errors.InvalidPatternException;
import org.eclipse.jgit.fnmatch.FileNameMatcher; import org.eclipse.jgit.fnmatch.FileNameMatcher;
@ -961,7 +962,7 @@ public class OpenSshConfig implements ConfigRepository {
/** /**
* Retrieves the full {@link com.jcraft.jsch.ConfigRepository.Config Config} * Retrieves the full {@link com.jcraft.jsch.ConfigRepository.Config Config}
* for the given host name. * for the given host name. Should be called only by Jsch and tests.
* *
* @param hostName * @param hostName
* to get the config for * to get the config for
@ -971,7 +972,7 @@ public class OpenSshConfig implements ConfigRepository {
@Override @Override
public Config getConfig(String hostName) { public Config getConfig(String hostName) {
Host host = lookup(hostName); Host host = lookup(hostName);
return host.getConfig(); return new JschBugFixingConfig(host.getConfig());
} }
@Override @Override
@ -980,4 +981,61 @@ public class OpenSshConfig implements ConfigRepository {
return "OpenSshConfig [home=" + home + ", configFile=" + configFile return "OpenSshConfig [home=" + home + ", configFile=" + configFile
+ ", lastModified=" + lastModified + ", state=" + state + "]"; + ", lastModified=" + lastModified + ", state=" + state + "]";
} }
/**
* A {@link com.jcraft.jsch.ConfigRepository.Config} that transforms some
* values from the config file into the format Jsch 0.1.54 expects. This is
* a work-around for bugs in Jsch.
*/
private static class JschBugFixingConfig implements Config {
private final Config real;
public JschBugFixingConfig(Config delegate) {
real = delegate;
}
@Override
public String getHostname() {
return real.getHostname();
}
@Override
public String getUser() {
return real.getUser();
}
@Override
public int getPort() {
return real.getPort();
}
@Override
public String getValue(String key) {
String result = real.getValue(key);
if (result != null) {
String k = key.toUpperCase(Locale.ROOT);
if ("SERVERALIVEINTERVAL".equals(k) //$NON-NLS-1$
|| "CONNECTTIMEOUT".equals(k)) { //$NON-NLS-1$
// These values are in seconds. Jsch 0.1.54 passes them on
// as is to java.net.Socket.setSoTimeout(), which expects
// milliseconds. So convert here to milliseconds...
try {
int timeout = Integer.parseInt(result);
result = Long
.toString(TimeUnit.SECONDS.toMillis(timeout));
} catch (NumberFormatException e) {
// Ignore
}
}
}
return result;
}
@Override
public String[] getValues(String key) {
return real.getValues(key);
}
}
} }

Loading…
Cancel
Save