Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds dynamic Settings for session connection timeout #85

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions src/main/java/com/jcabi/ssh/AbstractSshShell.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
@EqualsAndHashCode(of = { "addr", "port", "login" })
@Getter
@SuppressWarnings({ "PMD.UnusedPrivateField", "PMD.SingularField" })
abstract class AbstractSshShell implements Shell {

public abstract class AbstractSshShell implements Shell {
boolean disconnectAfter = true;
/**
* IP address of the server.
*/
Expand Down Expand Up @@ -81,6 +81,24 @@ abstract class AbstractSshShell implements Shell {
this.port = prt;
this.login = user;
}
/**
* Constructor.
* @param adr Address that you want to connect to.
* @param prt Port that you want to reach.
* @param user User that will be used when connecting.
* @param disconnectAfter disconnect session or not
* @throws UnknownHostException when host is unknown.
*/
AbstractSshShell(
final String adr,
final int prt,
final String user,
final boolean disconnectAfter) throws UnknownHostException {
this.addr = InetAddress.getByName(adr).getHostAddress();
this.port = prt;
this.login = user;
this.disconnectAfter = disconnectAfter;
}

// @checkstyle ParameterNumberCheck (2 lines)
@Override
Expand All @@ -93,7 +111,7 @@ public int exec(final String command, final InputStream stdin,
stdout,
stderr,
this.session()
).exec();
).exec(this.disconnectAfter);
}

/**
Expand Down
83 changes: 58 additions & 25 deletions src/main/java/com/jcabi/ssh/Execution.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Copyright (c) 2014-2017, jcabi.com
* All rights reserved.
*
* <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met: 1) Redistributions of source code must retain the above
Expand All @@ -13,7 +13,7 @@
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
Expand All @@ -33,27 +33,41 @@
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* Execution of a single command.
*
* @author Georgy Vlasov ([email protected])
* @version $Id$
* @since 1.4
*/
interface Execution {
/**
* Executes some command.
* Executes some command and disconnect
*
* @return Return code of the command.
* @throws IOException If fails
*/
int exec() throws IOException;

/**
* Executes some command.
*
* @param disconnectAfter Whether to disconnect session After executes some command
* @return Return code of the command.
* @throws IOException
*/
int exec(boolean disconnectAfter) throws IOException;

/**
* Execution of a command in an SSH session.
*
* @author Georgy Vlasov ([email protected])
* @version $Id$
* @since 1.4
Expand All @@ -62,8 +76,7 @@ final class Default implements Execution {
/**
* Command.
*/
private final transient String command;

private transient String command;
/**
* Stdin.
*/
Expand All @@ -87,16 +100,17 @@ final class Default implements Execution {
/**
* Uses an SSH session to execute a single command and disconnect
* immediately.
* @param cmd Command
*
* @param cmd Command
* @param input Stdin (will be closed)
* @param out Stdout (will be closed)
* @param err Stderr (will be closed)
* @param sess SSH session (will be disconnected)
* @param out Stdout (will be closed)
* @param err Stderr (will be closed)
* @param sess SSH session (will be disconnected)
* @checkstyle ParameterNumberCheck (6 lines)
*/
Default(final String cmd, final InputStream input,
final OutputStream out, final OutputStream err,
final Session sess) {
final OutputStream out, final OutputStream err,
final Session sess) {
this.command = cmd;
this.stdin = input;
this.stdout = out;
Expand All @@ -106,26 +120,44 @@ final class Default implements Execution {

@Override
public int exec() throws IOException {
try {
final ChannelExec channel = ChannelExec.class.cast(
return this.exec(true);
}

private int execCommand() throws JSchException, IOException {
final ChannelExec channel = ChannelExec.class.cast(
this.session.openChannel("exec")
);
channel.setErrStream(this.stderr, false);
channel.setOutputStream(this.stdout, false);
channel.setInputStream(this.stdin, false);
channel.setCommand(this.command);
channel.connect();
Logger.info(this, "$ %s", this.command);
return this.exec(channel);
} catch (final JSchException ex) {
throw new IOException(ex);
} finally {
this.session.disconnect();
);
channel.setErrStream(this.stderr, false);
channel.setOutputStream(this.stdout, false);
channel.setInputStream(this.stdin, false);
channel.setCommand(this.command);
channel.connect();
Logger.info(this, "$ %s", this.command);
return this.exec(channel);
}

@Override
public int exec(boolean disconnectAfter) throws IOException {
if (disconnectAfter) {
try {
return this.execCommand();
} catch (final JSchException ex) {
throw new IOException(ex);
} finally {
this.session.disconnect();
}
} else {
try {
return this.execCommand();
} catch (final JSchException ex) {
throw new IOException(ex);
}
}
}

/**
* Exec this channel and return its exit code.
*
* @param channel The channel to exec
* @return Exit code (zero in case of success)
* @throws IOException If fails
Expand All @@ -140,6 +172,7 @@ private int exec(final ChannelExec channel) throws IOException {

/**
* Wait until it's done and return its code.
*
* @param exec The channel
* @return The exit code
* @throws IOException If some IO problem inside
Expand Down
25 changes: 24 additions & 1 deletion src/main/java/com/jcabi/ssh/Ssh.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ public final class Ssh extends AbstractSshShell {
* Private SSH key pass phrase.
*/
private final transient String passphrase;
/**
* connect timeout
*/
private transient int serverAliveInterval = Tv.TEN;

/**
* Constructor.
Expand Down Expand Up @@ -216,6 +220,25 @@ public Ssh(final String adr, final int prt,
this.key = priv;
this.passphrase = passphrs;
}
/**
* Constructor.
* @param adr IP address
* @param prt Port of server
* @param user Login
* @param priv Private SSH key
* @param passphrs Pass phrase for encrypted priv. key
* @throws UnknownHostException when host is unknown.
* @checkstyle ParameterNumberCheck (6 lines)
*/
public Ssh(final String adr, final int prt,
final String user, final String priv,
final String passphrs ,final int serverAliveInterval
) throws UnknownHostException {
super(adr, prt, user);
this.key = priv;
this.passphrase = passphrs;
this.serverAliveInterval = serverAliveInterval;
}

/**
* Escape SSH argument.
Expand Down Expand Up @@ -272,7 +295,7 @@ protected Session session() throws IOException {
this.getLogin(), this.getAddr(), this.getPort()
);
session.setServerAliveInterval(
(int) TimeUnit.SECONDS.toMillis(Tv.TEN)
(int) TimeUnit.SECONDS.toMillis(this.serverAliveInterval)
);
session.setServerAliveCountMax(Tv.MILLION);
session.connect();
Expand Down
73 changes: 68 additions & 5 deletions src/main/java/com/jcabi/ssh/SshByPassword.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public final class SshByPassword extends AbstractSshShell {
* User password.
*/
private final transient String password;
/**
* session timeOut.
*/
private transient int serverAliveInterval = Tv.TEN;

private Session session = null;

/**
* Constructor.
Expand All @@ -72,6 +78,59 @@ public SshByPassword(final String adr, final int prt,
super(adr, prt, user);
this.password = passwd;
}
/**
* Constructor.
* @param adr IP address
* @param prt Port of server
* @param user Login
* @param passwd Password
* @param disconnectAfter disconnect session or not
* @throws UnknownHostException If fails
* @checkstyle ParameterNumberCheck (6 lines)
*/
public SshByPassword(final String adr, final int prt,
final String user, final String passwd,final boolean disconnectAfter)
throws UnknownHostException {
super(adr, prt, user);
this.password = passwd;
this.disconnectAfter = disconnectAfter;
}
/**
* Constructor.
* @param adr IP address
* @param prt Port of server
* @param user Login
* @param passwd Password
* @param serverAliveInterval (second)
* @throws UnknownHostException If fails
* @checkstyle ParameterNumberCheck (6 lines)
*/
public SshByPassword(final String adr, final int prt,
final String user, final String passwd,final int serverAliveInterval)
throws UnknownHostException {
super(adr, prt, user);
this.password = passwd;
this.serverAliveInterval = serverAliveInterval;
}
/**
* Constructor.
* @param adr IP address
* @param prt Port of server
* @param user Login
* @param passwd Password
* @param serverAliveInterval (second)
* @param disconnectAfter disconnect session or not
* @throws UnknownHostException If fails
* @checkstyle ParameterNumberCheck (6 lines)
*/
public SshByPassword(final String adr, final int prt,
final String user, final String passwd,final int serverAliveInterval,boolean disconnectAfter)
throws UnknownHostException {
super(adr, prt, user);
this.password = passwd;
this.serverAliveInterval = serverAliveInterval;
this.disconnectAfter = disconnectAfter;
}

// @checkstyle ProtectedMethodInFinalClassCheck (10 lines)
@Override
Expand All @@ -84,24 +143,28 @@ public SshByPassword(final String adr, final int prt,
types = IOException.class
)
protected Session session() throws IOException {
if (this.session!=null && this.session.isConnected()){
return this.session;
}
try {
JSch.setConfig("StrictHostKeyChecking", "no");
JSch.setLogger(new JschLogger());
final JSch jsch = new JSch();
Logger.debug(
this,
"Opening SSH session to %s@%s:%s (auth with password)...",
this.getLogin(), this.getAddr(), this.getPort()
this,
"Opening SSH session to %s@%s:%s (auth with password)...",
this.getLogin(), this.getAddr(), this.getPort()
);
final Session session = jsch.getSession(
this.getLogin(), this.getAddr(), this.getPort()
this.getLogin(), this.getAddr(), this.getPort()
);
session.setPassword(this.password);
session.setServerAliveInterval(
(int) TimeUnit.SECONDS.toMillis(Tv.TEN)
(int) TimeUnit.SECONDS.toMillis(this.serverAliveInterval)
);
session.setServerAliveCountMax(Tv.MILLION);
session.connect();
this.session = session;
return session;
} catch (final JSchException ex) {
throw new IOException(ex);
Expand Down