All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.hidetake.groovy.ssh.connection.ConnectionManager.groovy Maven / Gradle / Ivy
package org.hidetake.groovy.ssh.connection
import com.jcraft.jsch.JSch
import com.jcraft.jsch.JSchException
import groovy.util.logging.Slf4j
import org.hidetake.groovy.ssh.core.Remote
import org.hidetake.groovy.ssh.core.settings.GlobalSettings
import org.hidetake.groovy.ssh.core.settings.PerServiceSettings
import org.hidetake.groovy.ssh.session.forwarding.LocalPortForwardSettings
import static org.hidetake.groovy.ssh.util.Utility.retry
/**
* A manager of {@link Connection}s.
*
* @author Hidetake Iwata
*/
@Slf4j
class ConnectionManager implements Closeable, UserAuthentication, HostAuthentication, ProxyConnection {
/**
* Settings with default, global and per-service.
*/
private final ConnectionSettings connectionSettings
private final List connections = []
def ConnectionManager(GlobalSettings globalSettings, PerServiceSettings perServiceSettings) {
this(new ConnectionSettings.With(
ConnectionSettings.With.DEFAULT,
globalSettings,
perServiceSettings))
}
def ConnectionManager(ConnectionSettings connectionSettings1) {
connectionSettings = connectionSettings1
}
/**
* Establish a connection.
*
* @param remote target remote host
* @return a connection
*/
Connection connect(Remote remote) {
def settings = new ConnectionSettings.With(connectionSettings, remote)
if (settings.gateway && settings.gateway != remote) {
log.debug("Connecting to $remote via $settings.gateway")
def gatewayConnection = connect(settings.gateway)
log.debug("Requesting port forwarding to $remote")
def localPort = gatewayConnection.forwardLocalPort(new LocalPortForwardSettings.With(
host: remote.host, hostPort: remote.port, bind: '127.0.0.1', port: 0,
))
log.info("Enabled local port forwarding from localhost:$localPort to $remote")
connectInternal(remote, '127.0.0.1', localPort)
} else {
connectInternal(remote)
}
}
/**
* Establish a connection via given host and port.
*
* @param remote target remote host
* @param host endpoint host (usually remote.host
)
* @param port endpoint port (usually remote.port
)
* @return a connection
*/
private Connection connectInternal(Remote remote, String host = remote.host, int port = remote.port) {
def settings = new ConnectionSettings.With(connectionSettings, remote)
log.debug("Connecting to $remote with $settings")
validateHostAuthentication(settings, remote)
validateUserAuthentication(settings, remote)
validateProxyConnection(settings, remote)
assert settings.retryCount >= 0, "retryCount must be zero or positive ($remote)"
assert settings.retryWaitSec >= 0, "retryWaitSec must be zero or positive ($remote)"
assert settings.keepAliveSec >= 0, "keepAliveSec must be zero or positive ($remote)"
retry(settings.retryCount, settings.retryWaitSec) {
try {
connectInternal(remote, host, port, settings)
} catch (JSchException e) {
if (e.message.startsWith('UnknownHostKey') && settings.knownHosts instanceof AddHostKey) {
log.info(e.message)
reconnectToAddHostKey(remote, host, port, settings)
} else {
throw e
}
}
}
}
private Connection connectInternal(Remote remote, String host, int port, ConnectionSettings settings) {
def jsch = new JSch()
def session = jsch.getSession(settings.user, host, port)
session.setServerAliveInterval(settings.keepAliveSec * 1000)
session.timeout = settings.timeoutSec * 1000
configureHostAuthentication(jsch, session, remote, settings)
configureUserAuthentication(jsch, session, remote, settings)
configureProxyConnection(jsch, session, remote, settings)
session.connect()
def connection = new Connection(remote, session)
connections.add(connection)
log.info("Connected to $remote (${session.serverVersion})")
connection
}
private Connection reconnectToAddHostKey(Remote remote, String host, int port, ConnectionSettings settings) {
def addHostKey = settings.knownHosts as AddHostKey
settings.knownHosts = AllowAnyHosts.instance
def connection = connectInternal(remote, host, port, settings)
addHostKeyToKnownHostsFile(addHostKey, connection.session, remote)
log.info("Added host key received from $remote")
connection
}
void close() {
log.debug("Closing connections: $connections")
connections*.close()
connections.clear()
}
}