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 ExecutorService |
flushRunner
An
ExecutorService used to flush the queue asynchronously. |
protected boolean |
kexFlushed
Indicates that all pending packets have been flushed.
|
protected 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. |
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 final ReentrantReadWriteLock lock
protected final ExecutorService flushRunner
ExecutorService
used to flush the queue asynchronously.#flushQueue(DefaultKeyExchangeFuture)}
protected final AbstractSession session
AbstractSession
this KeyExchangeMessageHandler
belongs to.protected final org.slf4j.Logger log
Logger
to use.protected final Queue<PendingWriteFuture> pendingPackets
protected volatile boolean kexFlushed
protected volatile 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()
kexFlushed
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 TimeUnit
s to wait at most if the calling thread is blockedunit
- TimeUnit
of timeout
IoWriteFuture
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 TimeUnit
s to wait at most if the calling thread is blockedunit
- TimeUnit
of timeout
IoWriteFuture
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 sentPendingWriteFuture
protected void flushQueue(DefaultKeyExchangeFuture flushDone)
flushDone
- the future obtained from terminateKeyExchange()
; will be fulfilled once all pending packets
have been writtenCopyright © 2008–2024 The Apache Software Foundation. All rights reserved.