public class KeyExchangeMessageHandler extends Object
SshConstants.SSH_MSG_KEXINIT message is received.
Apache MINA sshd queues up high-level messages that threads try to send while a key exchange is ongoing, and sends them once the key exchange is done. Sending queued messages may make the peer re-trigger a new key exchange, in which case sending queued messages stops and is resumed at the end of the new key exchange.
| Modifier and Type | Field and Description |
|---|---|
protected static ExecutorService |
flushRunner
An
ExecutorService used to flush the queue asynchronously. |
protected AtomicBoolean |
kexFlushed
Indicates that all pending packets have been flushed.
|
protected AtomicReference<DefaultKeyExchangeFuture> |
kexFlushedFuture
Never
null. |
protected ReentrantReadWriteLock |
lock
We need the flushing thread to have priority over writing threads.
|
protected org.slf4j.Logger |
log
The
Logger to use. |
protected Queue<PendingWriteFuture> |
pendingPackets
Queues up high-level packets written during an ongoing key exchange.
|
protected AbstractSession |
session
The
AbstractSession this KeyExchangeMessageHandler belongs to. |
protected AtomicBoolean |
shutDown
Indicates that the handler has been shut down.
|
| Constructor and Description |
|---|
KeyExchangeMessageHandler(AbstractSession session,
org.slf4j.Logger log)
|
| Modifier and Type | Method and Description |
|---|---|
protected PendingWriteFuture |
enqueuePendingPacket(int cmd,
Buffer buffer)
Enqueues a packet to be written once a running key exchange terminates.
|
protected void |
flushQueue(DefaultKeyExchangeFuture flushDone)
Flushes all packets enqueued while a key exchange was ongoing.
|
DefaultKeyExchangeFuture |
initNewKeyExchange()
Initializes the state for a new key exchange.
|
protected boolean |
isBlockAllowed(int cmd)
Tells whether the calling thread may be blocked in
writePacket(Buffer, long, TimeUnit). |
void |
shutdown()
Pretends all pending packets had been written.
|
AbstractMap.SimpleImmutableEntry<Integer,DefaultKeyExchangeFuture> |
terminateKeyExchange()
To be called when the key exchange is done.
|
void |
updateState(Runnable update) |
<V> V |
updateState(Supplier<V> update) |
protected IoWriteFuture |
writeOrEnqueue(int cmd,
Buffer buffer,
long timeout,
TimeUnit unit)
Writes an SSH packet.
|
IoWriteFuture |
writePacket(Buffer buffer,
long timeout,
TimeUnit unit)
Writes a packet.
|
protected static ExecutorService flushRunner
ExecutorService used to flush the queue asynchronously.flushQueue(DefaultKeyExchangeFuture)protected final ReentrantReadWriteLock lock
protected final AbstractSession session
AbstractSession this KeyExchangeMessageHandler belongs to.protected final org.slf4j.Logger log
Logger to use.protected final Queue<PendingWriteFuture> pendingPackets
protected final AtomicBoolean kexFlushed
true by the flushing thread, or at the end
of KEX if there are no packets to be flushed. Set to false when a new KEX starts. Initially true.protected final AtomicBoolean shutDown
protected final AtomicReference<DefaultKeyExchangeFuture> kexFlushedFuture
null. Used to block some threads when writing packets while pending packets are still being flushed
at the end of a KEX to avoid overrunning the flushing thread. Always set, initially fulfilled. At the beginning
of a KEX a new future is installed, which is fulfilled at the end of the KEX once there are no more pending
packets to be flushed.public KeyExchangeMessageHandler(AbstractSession session, org.slf4j.Logger log)
session - AbstractSession the new instance belongs tolog - Logger to use for writing log messagespublic void updateState(Runnable update)
public <V> V updateState(Supplier<V> update)
public DefaultKeyExchangeFuture initNewKeyExchange()
allPacketsFlushed will be false, and a new future
to be fulfilled when all queued packets will be flushed once the key exchange is done is set. The currently set
future from an earlier key exchange is returned. The returned future may or may not be fulfilled; if it isn't,
there are still left-over pending packets to write from the previous key exchange, which will be written once the
new key exchange flushes pending packets.DefaultKeyExchangeFuture indicating whether all pending packets were flushed.public AbstractMap.SimpleImmutableEntry<Integer,DefaultKeyExchangeFuture> terminateKeyExchange()
flushQueue(DefaultKeyExchangeFuture) with that future as argument has flushed all pending
packets, if there are any.DefaultKeyExchangeFuture and the number of currently pending packetspublic void shutdown()
AbstractSession closes.public IoWriteFuture writePacket(Buffer buffer, long timeout, TimeUnit unit) throws IOException
flushQueue(DefaultKeyExchangeFuture) is called when the key exchange
is done. Packets written while there are still pending packets to be flushed will either be queued, too, or the
calling thread will be blocked with the given timeout until all packets have been flushed. Whether a write will
be blocked is determined by isBlockAllowed(int).
If a packet was written, a key exchange may be triggered via AbstractSession.checkRekey().
If timeout <= 0 or unit == null, a time-out of "forever" is assumed. Note that a timeout applies
only if the calling thread is blocked.
buffer - packet to writetimeout - number of TimeUnits to wait at most if the calling thread is blockedunit - TimeUnit of timeoutIoWriteFuture that will be fulfilled once the packet has indeed been written.IOException - if an error occursprotected IoWriteFuture writeOrEnqueue(int cmd, Buffer buffer, long timeout, TimeUnit unit) throws IOException
isBlockAllowed(int). If the calling thread holds
the monitor of the session's AbstractCloseable.getFutureLock(), it is never blocked and the write is
queued.
If timeout <= 0 or unit == null, a time-out of "forever" is assumed. Note that a timeout applies
only if the calling thread is blocked.
cmd - SSH command from the bufferbuffer - Buffer containing the packet to writetimeout - number of TimeUnits to wait at most if the calling thread is blockedunit - TimeUnit of timeoutIoWriteFuture that will be fulfilled once the packet has indeed been written.IOException - if an error occursprotected boolean isBlockAllowed(int cmd)
writePacket(Buffer, long, TimeUnit). This
implementation blocks writes of channel data packets unless written by an internal thread.
Typically an internal thread is one of the reading threads of Apache MINA sshd handling an SSH protocol message:
it's holding the AbstractSession.decodeLock; blocking it would mean we couldn't handle any other incoming
message, not even disconnections or another key exchange triggered by having lots of data queued.
cmd - SSH command of the buffer to be writtentrue if the thread may be blocked; false if the packet written must be
queued without blocking the threadprotected PendingWriteFuture enqueuePendingPacket(int cmd, Buffer buffer)
cmd - the SSH command from the bufferbuffer - the Buffer containing the packet to be sentPendingWriteFutureprotected void flushQueue(DefaultKeyExchangeFuture flushDone)
flushDone - the future obtained from getFlushedFuture; will be fulfilled once all pending packets
have been writtenCopyright © 2008–2024 The Apache Software Foundation. All rights reserved.