sshj icon indicating copy to clipboard operation
sshj copied to clipboard

Can't make read timeout work on inputstream

Open Nilliom opened this issue 5 years ago • 2 comments
trafficstars

Hi

I'm trying to write a program that access an equipment with SSH, listen in and when a certain amount of time has passed (10 seconds) without any characters coming in that would timeout from the read stream. I have looked at examples around the web and wrote this following code, but it does not work. The call to the read does not timeout at 10 seconds. Am I doing something wrong? Is there a bug in the library?

Thanks for your help...

Here is the code for the client:

`import java.io.*;

import net.schmizz.sshj.SSHClient; import net.schmizz.sshj.connection.channel.direct.Session; import net.schmizz.sshj.connection.channel.direct.SessionChannel; import java.io.IOException; import java.net.SocketTimeoutException; import net.schmizz.sshj.transport.verification.PromiscuousVerifier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;

public class Test implements Runnable { private static Logger log = LogManager.getLogger(Test.class);

private SSHClient sshClient=null;
private SessionChannel shell = null;
private InputStream inputStream=null;

public static void main(String... args) throws IOException {
    Runnable runnable = new Test();
    Thread thread=new Thread(runnable);
    thread.start();

}

public void run() {
    log.debug("Creating SSHClient");
    sshClient = new SSHClient();

    sshClient.addHostKeyVerifier(new PromiscuousVerifier());

    sshClient.setTimeout(10000);
    try {
        sshClient.connect("localhost", 2224);

        sshClient.authPassword("xxxxxxxx", "xxxxxxxx");

        Session session = sshClient.startSession();
        shell= (SessionChannel) session.startShell();

        inputStream = shell.getInputStream();

        try (BufferedInputStream in = new BufferedInputStream(inputStream)) {

            boolean stayIn = true;
            byte[] buffer = new byte[1024];

            log.debug("Timeout was set to {}",sshClient.getTimeout());
            while (stayIn) {
                int read = 0;

                try {
                    if (log.isDebugEnabled()) {
                        log.debug("Reading/Waiting stream");
                    }
                    read = in.read(buffer);
                    if (read!=-1) {
                        log.debug("Read {} characters", read);
                    }
                    else {
                        log.debug("End of stream", read);
                        break;
                    }
                } catch (SocketTimeoutException e) {
                    if (log.isDebugEnabled()) {
                        log.debug("SocketTimeoutException:, read={}", read);

                    }
                }
            }
        }
    } catch (Exception e) {
        log.error("SSH Could not connect",e);
    }

}

}`

Nilliom avatar Apr 27 '20 10:04 Nilliom

I tried something. I have used the sshClient.getSocket().setSoTimeout() and set it's value to 10000. When I read from that inputstream taken from sshclient.getSocket().getInputStream(), it DOES timeout, BUT when I look at the characters received from that stream they are garbage. Though If I read the input stream from the shell or session it will report the right characters, BUT will not timeout anymore

Anyone can help?

I just want to open my ssh connection, open the shell, read characters, and when I don;t receive any characters for a 10000 milli, to report an exception that will allow me to know I timed out.

Thanks

Nilliom avatar May 06 '20 15:05 Nilliom

You could build this yourself by running a separate thread that does the timeout and that closes the inputstream when the timeout expires.

hierynomus avatar Jun 02 '20 14:06 hierynomus