hierynomus / sshj

ssh, scp and sftp for java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Timeout not honored on hung connection

ben-manes opened this issue · comments

Despite setting timeouts where possible, I am seeing hung connections with a customer's sftp server. Is there a way to have this timeout?

try (Closer closer = Closer.create()) {
  SSHClient ssh = closer.register(new SSHClient());
  ssh.addHostKeyVerifier(new PromiscuousVerifier());
  ssh.setConnectTimeout(TIMEOUT_MS);
  ssh.setTimeout(TIMEOUT_MS);
  ssh.connect(settings.host(), settings.port());

  if (settings.password() == null) {
    KeyProvider keyProvider = ssh.loadKeys(settings.privateKey(),
        /* publicKey */ null, /* passwordFinder */ null);
    ssh.authPublickey(settings.username(), keyProvider);
  } else {
    ssh.authPassword(settings.username(), settings.password());
  }

  SFTPClient sftp = closer.register(ssh.newSFTPClient());
  sftp.getFileTransfer().setPreserveAttributes(false);
  sftp.getSFTPEngine().setTimeoutMs(TIMEOUT_MS);

  sftp.put(new FileSystemFile(settings.local().toFile()), settings.destination());

  // Disconnect prior to sftp.close() to avoid a timeout due to the server not ACK'ing
  ssh.disconnect();

  logger.info("Transfered file {} to sftp server {}@{}",
      FilenameUtils.getName(settings.destination()), settings.username(), settings.host());
}
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(java.base@10.0.1/Native Method)
	- waiting on <no object reference available>
	at java.lang.Object.wait(java.base@10.0.1/Object.java:328)
	at net.schmizz.sshj.connection.channel.Window$Remote.awaitExpansion(Window.java:86)
	- waiting to re-lock in wait() <0x000000065f366578> (a java.lang.Object)
	at net.schmizz.sshj.connection.channel.ChannelOutputStream$DataBuffer.flush(ChannelOutputStream.java:79)
	at net.schmizz.sshj.connection.channel.ChannelOutputStream$DataBuffer.flush(ChannelOutputStream.java:70)
	at net.schmizz.sshj.connection.channel.ChannelOutputStream.flush(ChannelOutputStream.java:182)
	- locked <0x000000065f3665c8> (a net.schmizz.sshj.connection.channel.ChannelOutputStream)
	at net.schmizz.sshj.sftp.SFTPEngine.transmit(SFTPEngine.java:297)
	- locked <0x000000065f3665f0> (a net.schmizz.sshj.sftp.SFTPEngine)
	at net.schmizz.sshj.sftp.SFTPEngine.request(SFTPEngine.java:130)
	at net.schmizz.sshj.sftp.RemoteFile.asyncWrite(RemoteFile.java:83)
	at net.schmizz.sshj.sftp.RemoteFile$RemoteFileOutputStream.write(RemoteFile.java:143)
	at net.schmizz.sshj.common.StreamCopier.write(StreamCopier.java:155)
	at net.schmizz.sshj.common.StreamCopier.copy(StreamCopier.java:132)
	at net.schmizz.sshj.sftp.SFTPFileTransfer$Uploader.uploadFile(SFTPFileTransfer.java:240)
	at net.schmizz.sshj.sftp.SFTPFileTransfer$Uploader.upload(SFTPFileTransfer.java:186)
	at net.schmizz.sshj.sftp.SFTPFileTransfer$Uploader.access$100(SFTPFileTransfer.java:166)
	at net.schmizz.sshj.sftp.SFTPFileTransfer.upload(SFTPFileTransfer.java:64)
	at net.schmizz.sshj.sftp.SFTPClient.put(SFTPClient.java:244)

I think this is due to awaitExpansion not having a timeout to fail the operation, as it waits indefinitely. Can this be patched to fail instead of block forever?

Do you consider sshj.connection.channel.Window to be a public API (as it is public) and be backwards compatible? As in, should I provide backwards compatible overload or make a breaking change?

If this can be pushed it will save me from moving to Commons VFS, so happy to send the PR :)

Window is not a class you typically interact with in using sshj, so no, not an API ;)