You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2016/02/26 17:47:00 UTC

[3/4] mina-sshd git commit: Added some more documentation comments to AbstractSession

Added some more documentation comments to AbstractSession


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/7f52ea81
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/7f52ea81
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/7f52ea81

Branch: refs/heads/master
Commit: 7f52ea81476cffdab8300b5c0471aa3099b7d7c4
Parents: dd38bc4
Author: Lyor Goldstein <ly...@gmail.com>
Authored: Fri Feb 26 18:46:58 2016 +0200
Committer: Lyor Goldstein <ly...@gmail.com>
Committed: Fri Feb 26 18:46:58 2016 +0200

----------------------------------------------------------------------
 .../common/session/helpers/AbstractSession.java | 127 ++++++++++++++-----
 1 file changed, 96 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/7f52ea81/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
index 384a99f..e7359b3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
@@ -137,14 +137,14 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
     protected final SessionListener sessionListenerProxy;
 
     /**
-     * Channel events listener
+     * Channel events listener container
      */
     protected final Collection<ChannelListener> channelListeners = new CopyOnWriteArraySet<>();
     protected final ChannelListener channelListenerProxy;
 
-    //
-    // Key exchange support
-    //
+    /*
+     * Key exchange support
+     */
     protected byte[] sessionId;
     protected String serverVersion;
     protected String clientVersion;
@@ -159,9 +159,9 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
     protected final AtomicReference<KexState> kexState = new AtomicReference<>(KexState.UNKNOWN);
     protected final AtomicReference<DefaultKeyExchangeFuture> kexFutureHolder = new AtomicReference<>(null);
 
-    //
-    // SSH packets encoding / decoding support
-    //
+    /*
+     * SSH packets encoding / decoding support
+     */
     protected Cipher outCipher;
     protected Cipher inCipher;
     protected int outCipherSize = 8;
@@ -186,9 +186,9 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
     protected long idleTimeoutStart = System.currentTimeMillis();
     protected final AtomicReference<TimeoutStatus> timeoutStatus = new AtomicReference<>(TimeoutStatus.NoTimeout);
 
-    //
-    // Rekeying
-    //
+    /*
+     * Rekeying
+     */
     protected final AtomicLong inPacketsCount = new AtomicLong(0L);
     protected final AtomicLong outPacketsCount = new AtomicLong(0L);
     protected final AtomicLong inBytesCount = new AtomicLong(0L);
@@ -216,8 +216,20 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
      * The factory manager used to retrieve factories of Ciphers, Macs and other objects
      */
     private final FactoryManager factoryManager;
+
+    /**
+     * The session specific properties
+     */
     private final Map<String, Object> properties = new ConcurrentHashMap<>();
+
+    /**
+     * Used to wait for global requests result synchronous wait
+     */
     private final AtomicReference<Object> requestResult = new AtomicReference<>();
+
+    /**
+     * Session specific attributes
+     */
     private final Map<AttributeKey<?>, Object> attributes = new ConcurrentHashMap<>();
     private ReservedSessionMessagesHandler reservedSessionMessagesHandler;
 
@@ -232,7 +244,6 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         super(ValidateUtils.checkNotNull(factoryManager, "No factory manager provided"));
         this.isServer = isServer;
         this.factoryManager = factoryManager;
-        this.reservedSessionMessagesHandler = factoryManager.getReservedSessionMessagesHandler();
         this.ioSession = ioSession;
         this.decoderBuffer = new SessionWorkBuffer(this);
 
@@ -252,11 +263,12 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
 
     /**
      * Retrieve the session from the MINA session.
-     * If the session has not been attached, an IllegalStateException
+     * If the session has not been attached, an {@link IllegalStateException}
      * will be thrown
      *
      * @param ioSession the MINA session
      * @return the session attached to the MINA session
+     * @see #getSession(IoSession, boolean)
      */
     public static AbstractSession getSession(IoSession ioSession) {
         return getSession(ioSession, false);
@@ -264,7 +276,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
 
     /**
      * Retrieve the session from the MINA session.
-     * If the session has not been attached and allowNull is <code>false</code>,
+     * If the session has not been attached and <tt>allowNull</tt> is <code>false</code>,
      * an {@link IllegalStateException} will be thrown, else a {@code null} will
      * be returned
      *
@@ -317,6 +329,12 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         return ioSession;
     }
 
+    /**
+     * @param knownAddress Any externally set peer address - e.g., due to some
+     * proxy mechanism meta-data
+     * @return The external address if not {@code null} otherwise, the {@code IoSession}
+     * peer address
+     */
     protected SocketAddress resolvePeerAddress(SocketAddress knownAddress) {
         if (knownAddress != null) {
             return knownAddress;
@@ -716,7 +734,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         synchronized (pendingPackets) {
             if (!pendingPackets.isEmpty()) {
                 if (log.isDebugEnabled()) {
-                    log.debug("handleNewKeys({}) Dequeing pending packets", this);
+                    log.debug("handleNewKeys({}) Dequeing {} pending packets", this, pendingPackets.size());
                 }
                 synchronized (encodeLock) {
                     PendingWriteFuture future;
@@ -727,6 +745,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
             }
             kexState.set(KexState.DONE);
         }
+
         synchronized (lock) {
             lock.notifyAll();
         }
@@ -897,6 +916,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
                 }
             }
         }
+
         try {
             return doWritePacket(buffer);
         } finally {
@@ -1022,6 +1042,10 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
 
                 synchronized (requestResult) {
                     while (isOpen() && (maxWaitMillis > 0L) && (requestResult.get() == null)) {
+                        if (log.isTraceEnabled()) {
+                            log.trace("request({})[{}] remaining wait={}", this, request, maxWaitMillis);
+                        }
+
                         long waitStart = System.nanoTime();
                         requestResult.wait(maxWaitMillis);
                         long waitEnd = System.nanoTime();
@@ -1415,6 +1439,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
                 log.debug("doReadIdentification({}) line='{}'", this, str);
             }
 
+            // if this is a server then only one line is expected
             if (server || str.startsWith("SSH-")) {
                 return str;
             }
@@ -1501,7 +1526,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
      * Receive the remote key exchange init message.
      * The packet data is returned for later use.
      *
-     * @param buffer   the buffer containing the key exchange init packet
+     * @param buffer   the {@link Buffer} containing the key exchange init packet
      * @param proposal the remote proposal to fill
      * @return the packet data
      */
@@ -1674,10 +1699,12 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
             inCompression = s2ccomp;
         }
         outCipherSize = outCipher.getIVSize();
+        // TODO add support for configurable compression level
         outCompression.init(Compression.Type.Deflater, -1);
 
         inCipherSize = inCipher.getIVSize();
         inMacResult = new byte[inMac.getBlockSize()];
+        // TODO add support for configurable compression level
         inCompression.init(Compression.Type.Inflater, -1);
 
         // see https://tools.ietf.org/html/rfc4344#section-3.2
@@ -1772,9 +1799,9 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
     }
 
     /**
-     * Send an unimplemented packet.  This packet should contain the
-     * sequence id of the unsupported packet: this number is assumed to
-     * be the last packet received.
+     * Send a {@code SSH_MSG_UNIMPLEMENTED} packet.  This packet should
+     * contain the sequence id of the unsupported packet: this number
+     * is assumed to be the last packet received.
      *
      * @return An {@link IoWriteFuture} that can be used to wait for packet write completion
      * @throws IOException if an error occurred sending the packet
@@ -1871,6 +1898,12 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         return guess;
     }
 
+    /**
+     * Indicates the reception of a {@code SSH_MSG_REQUEST_SUCCESS} message
+     *
+     * @param buffer The {@link Buffer} containing the message data
+     * @throws Exception If failed to handle the message
+     */
     protected void requestSuccess(Buffer buffer) throws Exception {
         // use a copy of the original data in case it is re-used on return
         Buffer resultBuf = ByteArrayBuffer.getCompactClone(buffer.array(), buffer.rpos(), buffer.available());
@@ -1881,6 +1914,12 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         }
     }
 
+    /**
+     * Indicates the reception of a {@code SSH_MSG_REQUEST_FAILURE} message
+     *
+     * @param buffer The {@link Buffer} containing the message data
+     * @throws Exception If failed to handle the message
+     */
     protected void requestFailure(Buffer buffer) throws Exception {
         synchronized (requestResult) {
             requestResult.set(GenericUtils.NULL);
@@ -1930,7 +1969,8 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
 
     @Override
     public ReservedSessionMessagesHandler getReservedSessionMessagesHandler() {
-        return reservedSessionMessagesHandler;
+        return resolveEffectiveProvider(ReservedSessionMessagesHandler.class,
+                reservedSessionMessagesHandler, getFactoryManager().getReservedSessionMessagesHandler());
     }
 
     @Override
@@ -1998,6 +2038,12 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         return channelListenerProxy;
     }
 
+    /**
+     * Sends a session event to all currently registered session listeners
+     *
+     * @param event The event to send
+     * @throws IOException If any of the registered listeners threw an exception.
+     */
     protected void sendSessionEvent(SessionListener.Event event) throws IOException {
         SessionListener listener = getSessionListenerProxy();
         try {
@@ -2027,25 +2073,40 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         return ValidateUtils.checkNotNull(kexFutureHolder.get(), "No current KEX future on state=%s", kexState.get());
     }
 
-    protected void checkRekey() throws IOException {
-        if (isRekeyRequired()) {
-            requestNewKeysExchange();
-        }
+    /**
+     * Checks if a re-keying is required and if so initiates it
+     *
+     * @return A {@link KeyExchangeFuture} to wait for the initiated exchange
+     * or {@code null} if no need to re-key or an exchange is already in progress
+     * @throws IOException If failed to send the request
+     * @see #isRekeyRequired()
+     * @see #requestNewKeysExchange()
+     */
+    protected KeyExchangeFuture checkRekey() throws IOException {
+        return isRekeyRequired() ? requestNewKeysExchange() : null;
     }
 
-    protected void requestNewKeysExchange() throws IOException {
+    /**
+     * Initiates a new keys exchange if one not already in progress
+     *
+     * @return A {@link KeyExchangeFuture} to wait for the initiated exchange
+     * or {@code null} if an exchange is already in progress
+     * @throws IOException If failed to send the request
+     */
+    protected KeyExchangeFuture requestNewKeysExchange() throws IOException {
         if (!kexState.compareAndSet(KexState.DONE, KexState.INIT)) {
             if (log.isDebugEnabled()) {
                 log.debug("requestNewKeysExchange({}) KEX state not DONE: {}", this, kexState.get());
             }
 
-            return;
+            return null;
         }
 
         log.info("requestNewKeysExchange({}) Initiating key re-exchange", this);
         sendKexInit();
 
-        DefaultKeyExchangeFuture kexFuture = kexFutureHolder.getAndSet(new DefaultKeyExchangeFuture(null));
+        DefaultKeyExchangeFuture newFuture = new DefaultKeyExchangeFuture(null);
+        DefaultKeyExchangeFuture kexFuture = kexFutureHolder.getAndSet(newFuture);
         if (kexFuture != null) {
             synchronized (kexFuture) {
                 Object value = kexFuture.getValue();
@@ -2054,6 +2115,8 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
                 }
             }
         }
+
+        return newFuture;
     }
 
     protected boolean isRekeyRequired() {
@@ -2175,6 +2238,12 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
      */
     protected abstract String resolveAvailableSignaturesProposal(FactoryManager manager);
 
+    /**
+     * Indicates the the key exchange is completed and the exchanged keys
+     * can now be verified - e.g., client can verify the server's key
+     *
+     * @throws IOException If validation failed
+     */
     protected abstract void checkKeys() throws IOException;
 
     protected void receiveKexInit(Buffer buffer) throws IOException {
@@ -2188,7 +2257,7 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
     // returns the proposal argument
     protected Map<KexProposalOption, String> mergeProposals(Map<KexProposalOption, String> current, Map<KexProposalOption, String> proposal) {
         if (current == proposal) {
-            return proposal; // debug breakpoint
+            return proposal; // nothing to merge
         }
 
         synchronized (current) {
@@ -2206,10 +2275,6 @@ public abstract class AbstractSession extends AbstractKexFactoryManager implemen
         return proposal;
     }
 
-    protected void serviceAccept() throws IOException {
-        // nothing
-    }
-
     /**
      * Checks whether the session has timed out (both auth and idle timeouts are checked).
      * If the session has timed out, a DISCONNECT message will be sent.