Package net.schmizz.sshj.transport
Class TransportImpl
- java.lang.Object
-
- net.schmizz.sshj.transport.TransportImpl
-
- All Implemented Interfaces:
RemoteAddressProvider
,SSHPacketHandler
,DisconnectListener
,Transport
public final class TransportImpl extends java.lang.Object implements Transport, DisconnectListener
A thread-safeTransport
implementation.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) static class
TransportImpl.ConnInfo
private static class
TransportImpl.NullService
-
Field Summary
Fields Modifier and Type Field Description private boolean
authed
private java.lang.String
clientID
Client version identification stringprivate Event<TransportException>
close
private Config
config
private TransportImpl.ConnInfo
connInfo
private Decoder
decoder
private DisconnectListener
disconnectListener
private Encoder
encoder
private KeyAlgorithm
hostKeyAlgorithm
private KeyExchanger
kexer
private org.slf4j.Logger
log
private LoggerFactory
loggerFactory
private Message
msg
Message identifier of last packet receivedprivate Service
nextService
The next service that will be activated, only set when sending an SSH_MSG_SERVICE_REQUESTprivate Service
nullService
private Reader
reader
private java.lang.String
serverID
Server version identification stringprivate Service
service
Currently active service e.g.private Event<TransportException>
serviceAccept
private int
timeoutMs
private java.util.concurrent.locks.ReentrantLock
writeLock
-
Constructor Summary
Constructors Constructor Description TransportImpl(Config config)
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addAlgorithmsVerifier(AlgorithmsVerifier verifier)
Adds the specified verifier.void
addHostKeyVerifier(HostKeyVerifier hkv)
Adds the specified verifier.void
die(java.lang.Exception ex)
Kill the transport in an exceptional way.void
disconnect()
Send a disconnection packet with reason asDisconnectReason.BY_APPLICATION
, and closes this transport.void
disconnect(DisconnectReason reason)
Send a disconnect packet with the givenreason
, and closes this transport.void
disconnect(DisconnectReason reason, java.lang.String message)
Send a disconnect packet with the givenreason
andmessage
, and closes this transport.void
doKex()
Do key exchange and algorithm negotiation.private void
finishOff()
(package private) java.lang.String
getClientID()
java.util.List<KeyAlgorithm>
getClientKeyAlgorithms(KeyType keyType)
java.lang.String
getClientVersion()
Config
getConfig()
(package private) TransportImpl.ConnInfo
getConnInfo()
(package private) Decoder
getDecoder()
DisconnectListener
getDisconnectListener()
(package private) Encoder
getEncoder()
KeyAlgorithm
getHostKeyAlgorithm()
java.lang.String
getRemoteHost()
int
getRemotePort()
java.net.InetSocketAddress
getRemoteSocketAddress()
Get Remote Socket Address using Connection Information(package private) java.lang.String
getServerID()
java.lang.String
getServerVersion()
Returns the version string as sent by the SSH server for identification purposes, e.g.Service
getService()
byte[]
getSessionID()
int
getTimeoutMs()
(package private) java.util.concurrent.locks.ReentrantLock
getWriteLock()
private void
gotDebug(SSHPacket buf)
private void
gotDisconnect(SSHPacket buf)
private void
gotServiceAccept()
private void
gotUnimplemented(SSHPacket packet)
Got an SSH_MSG_UNIMPLEMENTED, so lets see where we're at and act accordingly.void
handle(Message msg, SSHPacket buf)
This is where all incoming packets are handled.void
init(java.lang.String remoteHost, int remotePort, java.io.InputStream in, java.io.OutputStream out)
Sets the host information and the streams to be used by this transport.boolean
isAuthenticated()
boolean
isKexDone()
private static boolean
isKexerPacket(Message msg)
boolean
isRunning()
void
join()
Joins the thread calling this method to the transport's death.void
join(int timeout, java.util.concurrent.TimeUnit unit)
Joins the thread calling this method to the transport's death.void
notifyDisconnect(DisconnectReason reason, java.lang.String message)
TransportImpl implements its own default DisconnectListener.private java.lang.String
readIdentification(Buffer.PlainBuffer buffer)
Reads the identification string from the SSH server.private void
receiveServerIdent()
void
reqService(Service service)
Request a SSH service represented by aService
instance.private void
sendClientIdent()
Receive the server identification string.private void
sendDisconnect(DisconnectReason reason, java.lang.String message)
private void
sendServiceRequest(java.lang.String serviceName)
Sends a service request for the specified servicelong
sendUnimplemented()
Sends SSH_MSG_UNIMPLEMENTED in response to the last packet received.void
setAuthenticated()
Informs this transport that authentication has been completed.void
setDisconnectListener(DisconnectListener listener)
Specify alistener
that will be notified upon disconnection.void
setHostKeyAlgorithm(KeyAlgorithm keyAlgorithm)
void
setService(Service service)
Sets the currently activeService
.void
setTimeoutMs(int timeoutMs)
Set a timeout for methods that may block.long
write(SSHPacket payload)
Write a packet over this transport.
-
-
-
Field Detail
-
loggerFactory
private final LoggerFactory loggerFactory
-
log
private final org.slf4j.Logger log
-
nullService
private final Service nullService
-
config
private final Config config
-
kexer
private final KeyExchanger kexer
-
reader
private final Reader reader
-
encoder
private final Encoder encoder
-
decoder
private final Decoder decoder
-
hostKeyAlgorithm
private KeyAlgorithm hostKeyAlgorithm
-
serviceAccept
private final Event<TransportException> serviceAccept
-
close
private final Event<TransportException> close
-
clientID
private final java.lang.String clientID
Client version identification string
-
timeoutMs
private volatile int timeoutMs
-
authed
private volatile boolean authed
-
service
private volatile Service service
Currently active service e.g. UserAuthService, ConnectionService
-
nextService
private volatile Service nextService
The next service that will be activated, only set when sending an SSH_MSG_SERVICE_REQUEST
-
disconnectListener
private DisconnectListener disconnectListener
-
connInfo
private TransportImpl.ConnInfo connInfo
-
serverID
private java.lang.String serverID
Server version identification string
-
msg
private Message msg
Message identifier of last packet received
-
writeLock
private final java.util.concurrent.locks.ReentrantLock writeLock
-
-
Constructor Detail
-
TransportImpl
public TransportImpl(Config config)
-
-
Method Detail
-
init
public void init(java.lang.String remoteHost, int remotePort, java.io.InputStream in, java.io.OutputStream out) throws TransportException
Description copied from interface:Transport
Sets the host information and the streams to be used by this transport. Identification information is exchanged with the server. ATransportException
is thrown in case of SSH protocol version incompatibility.- Specified by:
init
in interfaceTransport
- Parameters:
remoteHost
- server's hostnameremotePort
- server's portin
- input stream for the connectionout
- output stream for the connection- Throws:
TransportException
- if there is an error during exchange of identification information
-
getRemoteSocketAddress
public java.net.InetSocketAddress getRemoteSocketAddress()
Get Remote Socket Address using Connection Information- Specified by:
getRemoteSocketAddress
in interfaceRemoteAddressProvider
- Returns:
- Remote Socket Address or null when not connected
-
notifyDisconnect
public void notifyDisconnect(DisconnectReason reason, java.lang.String message)
TransportImpl implements its own default DisconnectListener.- Specified by:
notifyDisconnect
in interfaceDisconnectListener
-
receiveServerIdent
private void receiveServerIdent() throws java.io.IOException
- Throws:
java.io.IOException
-
sendClientIdent
private void sendClientIdent() throws java.io.IOException
Receive the server identification string.- Throws:
java.io.IOException
- If there was an error writing to the outputstream.
-
readIdentification
private java.lang.String readIdentification(Buffer.PlainBuffer buffer) throws java.io.IOException
Reads the identification string from the SSH server. This is the very first string that is sent upon connection by the server. It takes the form of, e.g. "SSH-2.0-OpenSSH_ver". Several concerns are taken care of here, e.g. verifying protocol version, correct line endings as specified in RFC and such. This is not efficient but is only done once.- Parameters:
buffer
- The buffer to read from.- Returns:
- empty string if full ident string has not yet been received
- Throws:
java.io.IOException
- Thrown when protocol version is not supported
-
addHostKeyVerifier
public void addHostKeyVerifier(HostKeyVerifier hkv)
Description copied from interface:Transport
Adds the specified verifier.- Specified by:
addHostKeyVerifier
in interfaceTransport
- Parameters:
hkv
- the host key verifier
-
addAlgorithmsVerifier
public void addAlgorithmsVerifier(AlgorithmsVerifier verifier)
Description copied from interface:Transport
Adds the specified verifier.- Specified by:
addAlgorithmsVerifier
in interfaceTransport
- Parameters:
verifier
- The verifier to call with negotiated algorithms
-
doKex
public void doKex() throws TransportException
Description copied from interface:Transport
Do key exchange and algorithm negotiation. This can be the initial one or for algorithm renegotiation.- Specified by:
doKex
in interfaceTransport
- Throws:
TransportException
- if there was an error during key exchange
-
isKexDone
public boolean isKexDone()
-
getTimeoutMs
public int getTimeoutMs()
- Specified by:
getTimeoutMs
in interfaceTransport
- Returns:
- the timeout that is currently set for blocking operations.
-
setTimeoutMs
public void setTimeoutMs(int timeoutMs)
Description copied from interface:Transport
Set a timeout for methods that may block.- Specified by:
setTimeoutMs
in interfaceTransport
- Parameters:
timeoutMs
- the timeout in milliseconds
-
getRemoteHost
public java.lang.String getRemoteHost()
- Specified by:
getRemoteHost
in interfaceTransport
- Returns:
- the hostname to which this transport is connected.
-
getRemotePort
public int getRemotePort()
- Specified by:
getRemotePort
in interfaceTransport
- Returns:
- the port number on the remote host to which this transport is connected.
-
getClientVersion
public java.lang.String getClientVersion()
- Specified by:
getClientVersion
in interfaceTransport
- Returns:
- the version string used by this client to identify itself to an SSH server, e.g. "SSHJ_3_0"
-
getConfig
public Config getConfig()
-
getServerVersion
public java.lang.String getServerVersion()
Description copied from interface:Transport
Returns the version string as sent by the SSH server for identification purposes, e.g. "OpenSSH_$version". If the transport has not yet been initialized viaTransport.init(java.lang.String, int, java.io.InputStream, java.io.OutputStream)
, it will benull
.- Specified by:
getServerVersion
in interfaceTransport
- Returns:
- server's version string (may be
null
)
-
getSessionID
public byte[] getSessionID()
- Specified by:
getSessionID
in interfaceTransport
- Returns:
- the session identifier assigned by server
-
getService
public Service getService()
- Specified by:
getService
in interfaceTransport
- Returns:
- the currently active
Service
instance.
-
setService
public void setService(Service service)
Description copied from interface:Transport
Sets the currently activeService
. Handling of non-transport-layer packets isdelegated
to that service. For this method to be successful, at least one service request viaTransport.reqService(net.schmizz.sshj.Service)
must have been successful (not necessarily for the service being set).- Specified by:
setService
in interfaceTransport
- Parameters:
service
- (null-ok) theService
-
reqService
public void reqService(Service service) throws TransportException
Description copied from interface:Transport
Request a SSH service represented by aService
instance. A separate call toTransport.setService(net.schmizz.sshj.Service)
is not needed.- Specified by:
reqService
in interfaceTransport
- Parameters:
service
- the SSH service to be requested- Throws:
TransportException
- if the request failed for any reason
-
sendServiceRequest
private void sendServiceRequest(java.lang.String serviceName) throws TransportException
Sends a service request for the specified service- Parameters:
serviceName
- name of the service being requested- Throws:
TransportException
- if there is an error while sending the request
-
setAuthenticated
public void setAuthenticated()
Description copied from interface:Transport
Informs this transport that authentication has been completed. This method must be called after successful authentication, so that delayed compression may become effective if applicable.- Specified by:
setAuthenticated
in interfaceTransport
-
isAuthenticated
public boolean isAuthenticated()
- Specified by:
isAuthenticated
in interfaceTransport
- Returns:
- whether the transport thinks it is authenticated.
-
sendUnimplemented
public long sendUnimplemented() throws TransportException
Description copied from interface:Transport
Sends SSH_MSG_UNIMPLEMENTED in response to the last packet received.- Specified by:
sendUnimplemented
in interfaceTransport
- Returns:
- the sequence number of the packet sent
- Throws:
TransportException
- if an error occurred sending the packet
-
join
public void join() throws TransportException
Description copied from interface:Transport
Joins the thread calling this method to the transport's death.- Specified by:
join
in interfaceTransport
- Throws:
TransportException
- if the transport dies of an exception
-
join
public void join(int timeout, java.util.concurrent.TimeUnit unit) throws TransportException
Description copied from interface:Transport
Joins the thread calling this method to the transport's death.- Specified by:
join
in interfaceTransport
- Throws:
TransportException
- if the transport dies of an exception
-
isRunning
public boolean isRunning()
- Specified by:
isRunning
in interfaceTransport
- Returns:
- whether this transport is active.
The transport is considered to be running if it has been initialized without error via
Transport.init(java.lang.String, int, java.io.InputStream, java.io.OutputStream)
and has not been disconnected.
-
disconnect
public void disconnect()
Description copied from interface:Transport
Send a disconnection packet with reason asDisconnectReason.BY_APPLICATION
, and closes this transport.- Specified by:
disconnect
in interfaceTransport
-
disconnect
public void disconnect(DisconnectReason reason)
Description copied from interface:Transport
Send a disconnect packet with the givenreason
, and closes this transport.- Specified by:
disconnect
in interfaceTransport
- Parameters:
reason
- reason for disconnecting
-
disconnect
public void disconnect(DisconnectReason reason, java.lang.String message)
Description copied from interface:Transport
Send a disconnect packet with the givenreason
andmessage
, and closes this transport.- Specified by:
disconnect
in interfaceTransport
- Parameters:
reason
- the reason code for this disconnectmessage
- the text message
-
setDisconnectListener
public void setDisconnectListener(DisconnectListener listener)
Description copied from interface:Transport
Specify alistener
that will be notified upon disconnection.- Specified by:
setDisconnectListener
in interfaceTransport
- Parameters:
listener
- Disconnect Listener to be configured
-
getDisconnectListener
public DisconnectListener getDisconnectListener()
- Specified by:
getDisconnectListener
in interfaceTransport
- Returns:
- the current disconnect listener.
-
write
public long write(SSHPacket payload) throws TransportException
Description copied from interface:Transport
Write a packet over this transport. Thepayload
SSHPacket
should have 5 bytes free at the beginning to avoid a performance penalty associated with making space for header bytes (packet length, padding length).- Specified by:
write
in interfaceTransport
- Parameters:
payload
- theSSHPacket
containing data to send- Returns:
- sequence number of the sent packet
- Throws:
TransportException
- if an error occurred sending the packet
-
sendDisconnect
private void sendDisconnect(DisconnectReason reason, java.lang.String message)
-
handle
public void handle(Message msg, SSHPacket buf) throws SSHException
This is where all incoming packets are handled. If they pertain to the transport layer, they are handled here; otherwise they are delegated to the active service instance if any viaSSHPacketHandler.handle(net.schmizz.sshj.common.Message, net.schmizz.sshj.common.SSHPacket)
. Even among the transport layer specific packets, key exchange packets are delegated toKeyExchanger.handle(net.schmizz.sshj.common.Message, net.schmizz.sshj.common.SSHPacket)
. This method is called in the context of thereader
thread viaDecoder.received(byte[], int)
when a full packet has been decoded.- Specified by:
handle
in interfaceSSHPacketHandler
- Parameters:
msg
- the message identifierbuf
- buffer containing rest of the packet- Throws:
SSHException
- if an error occurs during handling (unrecoverable)
-
isKexerPacket
private static boolean isKexerPacket(Message msg)
-
gotDebug
private void gotDebug(SSHPacket buf) throws TransportException
- Throws:
TransportException
-
gotDisconnect
private void gotDisconnect(SSHPacket buf) throws TransportException
- Throws:
TransportException
-
gotServiceAccept
private void gotServiceAccept() throws TransportException
- Throws:
TransportException
-
gotUnimplemented
private void gotUnimplemented(SSHPacket packet) throws SSHException
Got an SSH_MSG_UNIMPLEMENTED, so lets see where we're at and act accordingly.- Parameters:
packet
- The 'unimplemented' packet received- Throws:
TransportException
- Thrown when key exchange is ongoingSSHException
-
finishOff
private void finishOff()
-
die
public void die(java.lang.Exception ex)
Description copied from interface:Transport
Kill the transport in an exceptional way.
-
getClientID
java.lang.String getClientID()
-
getServerID
java.lang.String getServerID()
-
getEncoder
Encoder getEncoder()
-
getDecoder
Decoder getDecoder()
-
getWriteLock
java.util.concurrent.locks.ReentrantLock getWriteLock()
-
getConnInfo
TransportImpl.ConnInfo getConnInfo()
-
setHostKeyAlgorithm
public void setHostKeyAlgorithm(KeyAlgorithm keyAlgorithm)
-
getHostKeyAlgorithm
public KeyAlgorithm getHostKeyAlgorithm()
- Specified by:
getHostKeyAlgorithm
in interfaceTransport
-
getClientKeyAlgorithms
public java.util.List<KeyAlgorithm> getClientKeyAlgorithms(KeyType keyType) throws TransportException
- Specified by:
getClientKeyAlgorithms
in interfaceTransport
- Throws:
TransportException
-
-