Class TransportImpl

java.lang.Object
net.schmizz.sshj.transport.TransportImpl
All Implemented Interfaces:
RemoteAddressProvider, SSHPacketHandler, DisconnectListener, Transport

public final class TransportImpl extends Object implements Transport, DisconnectListener
A thread-safe Transport implementation.
  • Field Details

    • 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 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 String serverID
      Server version identification string
    • msg

      private Message msg
      Message identifier of last packet received
    • writeLock

      private final ReentrantLock writeLock
  • Constructor Details

    • TransportImpl

      public TransportImpl(Config config)
  • Method Details

    • init

      public void init(String remoteHost, int remotePort, InputStream in, 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. A TransportException is thrown in case of SSH protocol version incompatibility.
      Specified by:
      init in interface Transport
      Parameters:
      remoteHost - server's hostname
      remotePort - server's port
      in - input stream for the connection
      out - output stream for the connection
      Throws:
      TransportException - if there is an error during exchange of identification information
    • getRemoteSocketAddress

      public InetSocketAddress getRemoteSocketAddress()
      Get Remote Socket Address using Connection Information
      Specified by:
      getRemoteSocketAddress in interface RemoteAddressProvider
      Returns:
      Remote Socket Address or null when not connected
    • notifyDisconnect

      public void notifyDisconnect(DisconnectReason reason, String message)
      TransportImpl implements its own default DisconnectListener.
      Specified by:
      notifyDisconnect in interface DisconnectListener
    • receiveServerIdent

      private void receiveServerIdent() throws IOException
      Throws:
      IOException
    • sendClientIdent

      private void sendClientIdent() throws IOException
      Receive the server identification string.
      Throws:
      IOException - If there was an error writing to the outputstream.
    • readIdentification

      private String readIdentification(Buffer.PlainBuffer buffer) throws 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:
      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 interface Transport
      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 interface Transport
      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 interface Transport
      Throws:
      TransportException - if there was an error during key exchange
    • isKexDone

      public boolean isKexDone()
    • getTimeoutMs

      public int getTimeoutMs()
      Specified by:
      getTimeoutMs in interface Transport
      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 interface Transport
      Parameters:
      timeoutMs - the timeout in milliseconds
    • getRemoteHost

      public String getRemoteHost()
      Specified by:
      getRemoteHost in interface Transport
      Returns:
      the hostname to which this transport is connected.
    • getRemotePort

      public int getRemotePort()
      Specified by:
      getRemotePort in interface Transport
      Returns:
      the port number on the remote host to which this transport is connected.
    • getClientVersion

      public String getClientVersion()
      Specified by:
      getClientVersion in interface Transport
      Returns:
      the version string used by this client to identify itself to an SSH server, e.g. "SSHJ_3_0"
    • getConfig

      public Config getConfig()
      Specified by:
      getConfig in interface Transport
      Returns:
      the Config associated with this transport.
    • getServerVersion

      public 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 via Transport.init(String, int, InputStream, OutputStream), it will be null.

      Specified by:
      getServerVersion in interface Transport
      Returns:
      server's version string (may be null)
    • getSessionID

      public byte[] getSessionID()
      Specified by:
      getSessionID in interface Transport
      Returns:
      the session identifier assigned by server
    • getService

      public Service getService()
      Specified by:
      getService in interface Transport
      Returns:
      the currently active Service instance.
    • setService

      public void setService(Service service)
      Description copied from interface: Transport
      Sets the currently active Service. Handling of non-transport-layer packets is delegated to that service.

      For this method to be successful, at least one service request via Transport.reqService(Service) must have been successful (not necessarily for the service being set).

      Specified by:
      setService in interface Transport
      Parameters:
      service - (null-ok) the Service
    • reqService

      public void reqService(Service service) throws TransportException
      Description copied from interface: Transport
      Request a SSH service represented by a Service instance. A separate call to Transport.setService(Service) is not needed.
      Specified by:
      reqService in interface Transport
      Parameters:
      service - the SSH service to be requested
      Throws:
      TransportException - if the request failed for any reason
    • sendServiceRequest

      private void sendServiceRequest(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 interface Transport
    • isAuthenticated

      public boolean isAuthenticated()
      Specified by:
      isAuthenticated in interface Transport
      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 interface Transport
      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 interface Transport
      Throws:
      TransportException - if the transport dies of an exception
    • join

      public void join(int timeout, TimeUnit unit) throws TransportException
      Description copied from interface: Transport
      Joins the thread calling this method to the transport's death.
      Specified by:
      join in interface Transport
      Throws:
      TransportException - if the transport dies of an exception
    • isRunning

      public boolean isRunning()
      Specified by:
      isRunning in interface Transport
      Returns:
      whether this transport is active.

      The transport is considered to be running if it has been initialized without error via Transport.init(String, int, InputStream, OutputStream) and has not been disconnected.

    • disconnect

      public void disconnect()
      Description copied from interface: Transport
      Send a disconnection packet with reason as DisconnectReason.BY_APPLICATION, and closes this transport.
      Specified by:
      disconnect in interface Transport
    • disconnect

      public void disconnect(DisconnectReason reason)
      Description copied from interface: Transport
      Send a disconnect packet with the given reason, and closes this transport.
      Specified by:
      disconnect in interface Transport
      Parameters:
      reason - reason for disconnecting
    • disconnect

      public void disconnect(DisconnectReason reason, String message)
      Description copied from interface: Transport
      Send a disconnect packet with the given reason and message, and closes this transport.
      Specified by:
      disconnect in interface Transport
      Parameters:
      reason - the reason code for this disconnect
      message - the text message
    • setDisconnectListener

      public void setDisconnectListener(DisconnectListener listener)
      Description copied from interface: Transport
      Specify a listener that will be notified upon disconnection.
      Specified by:
      setDisconnectListener in interface Transport
      Parameters:
      listener - Disconnect Listener to be configured
    • getDisconnectListener

      public DisconnectListener getDisconnectListener()
      Specified by:
      getDisconnectListener in interface Transport
      Returns:
      the current disconnect listener.
    • write

      public long write(SSHPacket payload) throws TransportException
      Description copied from interface: Transport
      Write a packet over this transport.

      The payload 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 interface Transport
      Parameters:
      payload - the SSHPacket 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, 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 via SSHPacketHandler.handle(Message, SSHPacket).

      Even among the transport layer specific packets, key exchange packets are delegated to KeyExchanger.handle(Message, SSHPacket).

      This method is called in the context of the reader thread via Decoder.received(byte[], int) when a full packet has been decoded.

      Specified by:
      handle in interface SSHPacketHandler
      Parameters:
      msg - the message identifier
      buf - 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 ongoing
      SSHException
    • finishOff

      private void finishOff()
    • die

      public void die(Exception ex)
      Description copied from interface: Transport
      Kill the transport in an exceptional way.
      Specified by:
      die in interface Transport
      Parameters:
      ex - The exception that occurred.
    • getClientID

      String getClientID()
    • getServerID

      String getServerID()
    • getEncoder

      Encoder getEncoder()
    • getDecoder

      Decoder getDecoder()
    • getWriteLock

      ReentrantLock getWriteLock()
    • getConnInfo

      TransportImpl.ConnInfo getConnInfo()
    • setHostKeyAlgorithm

      public void setHostKeyAlgorithm(KeyAlgorithm keyAlgorithm)
    • getHostKeyAlgorithm

      public KeyAlgorithm getHostKeyAlgorithm()
      Specified by:
      getHostKeyAlgorithm in interface Transport
    • getClientKeyAlgorithms

      public List<KeyAlgorithm> getClientKeyAlgorithms(KeyType keyType) throws TransportException
      Specified by:
      getClientKeyAlgorithms in interface Transport
      Throws:
      TransportException