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 2020/05/15 07:25:15 UTC

[mina-sshd] branch SSHD-966 created (now b0159a4)

This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a change to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git.


      at b0159a4  [SSHD-966] Using same lock to synchronize session pending packets and ChannelOutputStream mutual exclusion

This branch includes the following new commits:

     new 8c9b9a2  Upgraded Checkstyle version to 8.32
     new 6e40b23  Upgraded Groovy version to 2.5.11
     new ab2dc90  Upgraded ByteBuddy version to 1.10.10
     new 9cad293  Upgraded Spring Core version to 5.2.6
     new d1df42e  Upgraded PMD version to 6.23.0
     new 9dc5cc9  Upgraded ANT version to 1.10.8
     new 7a23ed1  Upraded testcontainers version to 1.14.1
     new bff5387  Upgraded Spring Integration version to 5.3.0
     new 966b609  Upgraded Netty version to 4.1.50
     new 9d92a4a  Upgraded Maven ANT plugin version to 3.0.0
     new 0f28c29  Upgraded Maven assembly plugin version to 3.3.0
     new d23d80d  Upgraded Maven dependency plugin version to 3.1.2
     new 2ef5f5f  Upgraded Maven enforcer plugin version to 3.0.0-M3
     new f4aa397  Upgraded Maven javadoc plugin version to 3.2.0
     new 9389943  Upgraded Maven remote resources plugin version to 1.7.0
     new 1a47365  Upgraded Maven build helper plugin version to 3.1.0
     new b0159a4  [SSHD-966] Using same lock to synchronize session pending packets and ChannelOutputStream mutual exclusion

The 17 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[mina-sshd] 16/17: Upgraded Maven build helper plugin version to 3.1.0

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 1a47365ae93e52db017b6aa1ee1d618904f01546
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:20:13 2020 +0300

    Upgraded Maven build helper plugin version to 3.1.0
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 8103cd9..c22a1e8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,7 +94,7 @@
         <maven.compiler.source>${javac.source}</maven.compiler.source>
         <ant.version>1.10.8</ant.version>
         <ant.build.javac.source>${javac.source}</ant.build.javac.source>
-        <build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version>
+        <build-helper-maven-plugin.version>3.1.0</build-helper-maven-plugin.version>
 
         <javac.target>${javac.source}</javac.target>
         <project.build.java.target>${javac.target}</project.build.java.target>


[mina-sshd] 06/17: Upgraded ANT version to 1.10.8

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 9dc5cc967a4b4a213a392ec26770b4b5d625f797
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:10:53 2020 +0300

    Upgraded ANT version to 1.10.8
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index d8f4a9a..88ca38c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -92,7 +92,7 @@
         <javac.source>${java.major.version}.${java.minor.version}</javac.source>
         <project.build.java.source>${javac.source}</project.build.java.source>
         <maven.compiler.source>${javac.source}</maven.compiler.source>
-        <ant.version>1.10.7</ant.version>
+        <ant.version>1.10.8</ant.version>
         <ant.build.javac.source>${javac.source}</ant.build.javac.source>
         <build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version>
 


[mina-sshd] 17/17: [SSHD-966] Using same lock to synchronize session pending packets and ChannelOutputStream mutual exclusion

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit b0159a4f22f7dcdab9a6b8824f6702547ab13058
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 10:24:50 2020 +0300

    [SSHD-966] Using same lock to synchronize session pending packets and ChannelOutputStream mutual exclusion
---
 .../sshd/common/channel/ChannelOutputStream.java   | 224 +++++++++++++--------
 .../common/session/helpers/AbstractSession.java    |  98 +++++++--
 2 files changed, 216 insertions(+), 106 deletions(-)

diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java
index d0d879b..c2f48f2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java
@@ -26,11 +26,14 @@ import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.RuntimeSshException;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.channel.exception.SshChannelClosedException;
 import org.apache.sshd.common.io.PacketWriter;
 import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.helpers.AbstractSession;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.slf4j.Logger;
@@ -103,24 +106,63 @@ public class ChannelOutputStream extends OutputStream implements java.nio.channe
     }
 
     @Override
-    public synchronized void write(int w) throws IOException {
-        b[0] = (byte) w;
-        write(b, 0, 1);
+    public void write(int w) throws IOException {
+        try {
+            Channel channel = getChannel();
+            Session session = channel.getSession();
+            ((AbstractSession) session).executeUnderPendingPacketsLock(
+                    getExtraPendingPacketLockWaitTime(1), () -> {
+                        b[0] = (byte) w;
+                        lockedWrite(session, channel, b, 0, 1);
+                        return null;
+                    });
+        } catch (Exception e) {
+            log.error("write(" + this + ") value=0x" + Integer.toHexString(w) + " failed to write", e);
+            if (e instanceof IOException) {
+                throw (IOException) e;
+            } else if (e instanceof RuntimeException) {
+                throw (RuntimeException) e;
+            } else {
+                throw new RuntimeSshException(e);
+            }
+        }
     }
 
     @Override
-    public synchronized void write(byte[] buf, int s, int l) throws IOException {
-        Channel channel = getChannel();
+    public void write(byte[] buf, int startOffset, int dataLen) throws IOException {
+        try {
+            Channel channel = getChannel();
+            Session session = channel.getSession();
+            ((AbstractSession) session).executeUnderPendingPacketsLock(
+                    getExtraPendingPacketLockWaitTime(dataLen), () -> {
+                        lockedWrite(session, channel, buf, startOffset, dataLen);
+                        return null;
+                    });
+        } catch (Exception e) {
+            log.error("write(" + this + ") len=" + dataLen + " failed to write", e);
+            if (e instanceof IOException) {
+                throw (IOException) e;
+            } else if (e instanceof RuntimeException) {
+                throw (RuntimeException) e;
+            } else {
+                throw new RuntimeSshException(e);
+            }
+        }
+    }
+
+    protected void lockedWrite(
+            Session session, Channel channel, byte[] buf, int startOffset, int dataLen)
+                throws Exception {
         if (!isOpen()) {
             throw new SshChannelClosedException(
                     channel.getId(),
-                    "write(" + this + ") len=" + l + " - channel already closed");
+                    "write(" + this + ") len=" + dataLen + " - channel already closed");
         }
 
-        Session session = channel.getSession();
+
         boolean debugEnabled = log.isDebugEnabled();
         boolean traceEnabled = log.isTraceEnabled();
-        while (l > 0) {
+        while (dataLen > 0) {
             // The maximum amount we should admit without flushing again
             // is enough to make up one full packet within our allowed
             // window size. We give ourselves a credit equal to the last
@@ -128,7 +170,7 @@ public class ChannelOutputStream extends OutputStream implements java.nio.channe
             // out the next packet before we block and wait for space to
             // become available again.
             long minReqLen = Math.min(remoteWindow.getSize() + lastSize, remoteWindow.getPacketSize());
-            long l2 = Math.min(l, minReqLen - bufferLength);
+            long l2 = Math.min(dataLen, minReqLen - bufferLength);
             if (l2 <= 0) {
                 if (bufferLength > 0) {
                     flush();
@@ -137,22 +179,22 @@ public class ChannelOutputStream extends OutputStream implements java.nio.channe
                     try {
                         long available = remoteWindow.waitForSpace(maxWaitTimeout);
                         if (traceEnabled) {
-                            log.trace("write({}) len={} - available={}", this, l, available);
+                            log.trace("write({}) len={} - available={}", this, dataLen, available);
                         }
                     } catch (IOException e) {
                         log.error("write({}) failed ({}) to wait for space of len={}: {}",
-                                this, e.getClass().getSimpleName(), l, e.getMessage());
+                                this, e.getClass().getSimpleName(), dataLen, e.getMessage());
 
                         if ((e instanceof WindowClosedException) && (!closedState.getAndSet(true))) {
                             if (debugEnabled) {
-                                log.debug("write({})[len={}] closing due to window closed", this, l);
+                                log.debug("write({})[len={}] closing due to window closed", this, dataLen);
                             }
                         }
 
                         throw e;
                     } catch (InterruptedException e) {
                         throw (IOException) new InterruptedIOException(
-                                "Interrupted while waiting for remote space on write len=" + l + " to " + this)
+                                "Interrupted while waiting for remote space on write len=" + dataLen + " to " + this)
                                         .initCause(e);
                     }
                 }
@@ -162,10 +204,10 @@ public class ChannelOutputStream extends OutputStream implements java.nio.channe
 
             ValidateUtils.checkTrue(l2 <= Integer.MAX_VALUE,
                     "Accumulated bytes length exceeds int boundary: %d", l2);
-            buffer.putRawBytes(buf, s, (int) l2);
+            buffer.putRawBytes(buf, startOffset, (int) l2);
             bufferLength += l2;
-            s += l2;
-            l -= l2;
+            startOffset += l2;
+            dataLen -= l2;
         }
 
         if (isNoDelay()) {
@@ -176,67 +218,74 @@ public class ChannelOutputStream extends OutputStream implements java.nio.channe
     }
 
     @Override
-    public synchronized void flush() throws IOException {
-        AbstractChannel channel = getChannel();
-        if (!isOpen()) {
-            throw new SshChannelClosedException(
-                    channel.getId(),
-                    "flush(" + this + ") length=" + bufferLength + " - stream is already closed");
-        }
-
+    public void flush() throws IOException {
+        Channel channel = getChannel();
+        Session session = channel.getSession();
         try {
-            Session session = channel.getSession();
-            boolean traceEnabled = log.isTraceEnabled();
-            while (bufferLength > 0) {
-                session.resetIdleTimeout();
+            ((AbstractSession) session).executeUnderPendingPacketsLock(
+                    getExtraPendingPacketLockWaitTime(bufferLength),
+                    () -> {
+                        if (!isOpen()) {
+                            throw new SshChannelClosedException(
+                                    channel.getId(),
+                                    "flush(" + this + ") length=" + bufferLength + " - stream is already closed");
+                        }
 
-                Buffer buf = buffer;
-                long total = bufferLength;
-                long available;
-                try {
-                    available = remoteWindow.waitForSpace(maxWaitTimeout);
-                    if (traceEnabled) {
-                        log.trace("flush({}) len={}, available={}", this, total, available);
-                    }
-                } catch (IOException e) {
-                    log.error("flush({}) failed ({}) to wait for space of len={}: {}",
-                            this, e.getClass().getSimpleName(), total, e.getMessage());
-                    if (log.isDebugEnabled()) {
-                        log.error("flush(" + this + ") wait for space len=" + total + " exception details", e);
-                    }
-                    throw e;
-                }
+                        boolean traceEnabled = log.isTraceEnabled();
+                        while (bufferLength > 0) {
+                            session.resetIdleTimeout();
 
-                long lenToSend = Math.min(available, total);
-                long length = Math.min(lenToSend, remoteWindow.getPacketSize());
-                if (length > Integer.MAX_VALUE) {
-                    throw new StreamCorruptedException(
-                            "Accumulated " + SshConstants.getCommandMessageName(cmd)
-                                                       + " command bytes size (" + length + ") exceeds int boundaries");
-                }
+                            Buffer buf = buffer;
+                            long total = bufferLength;
+                            long available;
+                            try {
+                                available = remoteWindow.waitForSpace(maxWaitTimeout);
+                                if (traceEnabled) {
+                                    log.trace("flush({}) len={}, available={}", this, total, available);
+                                }
+                            } catch (IOException e) {
+                                log.error("flush({}) failed ({}) to wait for space of len={}: {}",
+                                        this, e.getClass().getSimpleName(), total, e.getMessage());
+                                if (log.isDebugEnabled()) {
+                                    log.error("flush(" + this + ") wait for space len=" + total + " exception details", e);
+                                }
+                                throw e;
+                            }
 
-                int pos = buf.wpos();
-                buf.wpos((cmd == SshConstants.SSH_MSG_CHANNEL_EXTENDED_DATA) ? 14 : 10);
-                buf.putInt(length);
-                buf.wpos(buf.wpos() + (int) length);
-                if (total == length) {
-                    newBuffer((int) length);
-                } else {
-                    long leftover = total - length;
-                    newBuffer((int) Math.max(leftover, length));
-                    buffer.putRawBytes(buf.array(), pos - (int) leftover, (int) leftover);
-                    bufferLength = (int) leftover;
-                }
-                lastSize = (int) length;
+                            long lenToSend = Math.min(available, total);
+                            long length = Math.min(lenToSend, remoteWindow.getPacketSize());
+                            if (length > Integer.MAX_VALUE) {
+                                throw new StreamCorruptedException(
+                                        "Accumulated " + SshConstants.getCommandMessageName(cmd)
+                                                                   + " command bytes size (" + length
+                                                                   + ") exceeds int boundaries");
+                            }
 
-                session.resetIdleTimeout();
-                remoteWindow.waitAndConsume(length, maxWaitTimeout);
-                if (traceEnabled) {
-                    log.trace("flush({}) send {} len={}",
-                            channel, SshConstants.getCommandMessageName(cmd), length);
-                }
-                packetWriter.writePacket(buf);
-            }
+                            int pos = buf.wpos();
+                            buf.wpos((cmd == SshConstants.SSH_MSG_CHANNEL_EXTENDED_DATA) ? 14 : 10);
+                            buf.putInt(length);
+                            buf.wpos(buf.wpos() + (int) length);
+                            if (total == length) {
+                                newBuffer((int) length);
+                            } else {
+                                long leftover = total - length;
+                                newBuffer((int) Math.max(leftover, length));
+                                buffer.putRawBytes(buf.array(), pos - (int) leftover, (int) leftover);
+                                bufferLength = (int) leftover;
+                            }
+                            lastSize = (int) length;
+
+                            session.resetIdleTimeout();
+                            remoteWindow.waitAndConsume(length, maxWaitTimeout);
+                            if (traceEnabled) {
+                                log.trace("flush({}) send {} len={}",
+                                        channel, SshConstants.getCommandMessageName(cmd), length);
+                            }
+                            packetWriter.writePacket(buf);
+                        }
+
+                        return null;
+                    });
         } catch (WindowClosedException e) {
             if (!closedState.getAndSet(true)) {
                 if (log.isDebugEnabled()) {
@@ -257,8 +306,13 @@ public class ChannelOutputStream extends OutputStream implements java.nio.channe
         }
     }
 
+    protected long getExtraPendingPacketLockWaitTime(int dataSize) {
+        // TODO see if can do anything better
+        return Math.min(dataSize, FactoryManager.DEFAULT_NIO2_MIN_WRITE_TIMEOUT);
+    }
+
     @Override
-    public synchronized void close() throws IOException {
+    public void close() throws IOException {
         if (!isOpen()) {
             return;
         }
@@ -267,20 +321,22 @@ public class ChannelOutputStream extends OutputStream implements java.nio.channe
             log.trace("close({}) closing", this);
         }
 
-        try {
-            flush();
-
-            if (isEofOnClose()) {
-                AbstractChannel channel = getChannel();
-                channel.sendEof();
-            }
-        } finally {
+        synchronized (closedState) {
             try {
-                if (!(packetWriter instanceof Channel)) {
-                    packetWriter.close();
+                flush();
+
+                if (isEofOnClose()) {
+                    AbstractChannel channel = getChannel();
+                    channel.sendEof();
                 }
             } finally {
-                closedState.set(true);
+                try {
+                    if (!(packetWriter instanceof Channel)) {
+                        packetWriter.close();
+                    }
+                } finally {
+                    closedState.set(true);
+                }
             }
         }
     }
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 47a56b9..849a561 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
@@ -35,10 +35,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Queue;
+import java.util.concurrent.Callable;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Level;
 
 import org.apache.sshd.common.Closeable;
@@ -187,6 +192,7 @@ public abstract class AbstractSession extends SessionHelper {
     protected long maxRekyPackets = FactoryManager.DEFAULT_REKEY_PACKETS_LIMIT;
     protected long maxRekeyBytes = FactoryManager.DEFAULT_REKEY_BYTES_LIMIT;
     protected long maxRekeyInterval = FactoryManager.DEFAULT_REKEY_TIME_LIMIT;
+    protected final Lock pendingPacketsLock = new ReentrantLock();
     protected final Queue<PendingWriteFuture> pendingPackets = new LinkedList<>();
 
     protected Service currentService;
@@ -656,6 +662,38 @@ public abstract class AbstractSession extends SessionHelper {
         doKexNegotiation();
     }
 
+    /**
+     * Attempts to lock the pending packets access and execute the relevant code. Max. wait time is derived from the
+     * current number of pending packets
+     *
+     * @param  <V>       The executed code return value
+     * @param  extraWait An extra amount of time (msec.) that the caller is willing to wait beyond the time derived from
+     *                   the number of pending packets. <B>Note:</B> a hardcoded max. value of
+     *                   {@link FactoryManager#DEFAULT_AUTH_TIMEOUT} is imposed on the total calculated time.
+     * @param  executor  The code to execute under lock
+     * @return           The executed code result
+     * @throws Exception If failed to lock or exception thrown by executor code
+     * @see              <A HREF="https://issues.apache.org/jira/browse/SSHD-966">SSHD-966</A>
+     */
+    public <V> V executeUnderPendingPacketsLock(long extraWait, Callable<? extends V> executor) throws Exception {
+        ValidateUtils.checkTrue(extraWait >= 0L, "Invalid extra wait time: %d", extraWait);
+        int numPending = pendingPackets.size();
+        long maxWait = numPending * FactoryManager.DEFAULT_NIO2_MIN_WRITE_TIMEOUT + extraWait;
+        // in case zero
+        maxWait = Math.max(maxWait, FactoryManager.DEFAULT_NIO2_MIN_WRITE_TIMEOUT);
+        // in case lots of pending packets or large extra time
+        maxWait = Math.min(maxWait, FactoryManager.DEFAULT_AUTH_TIMEOUT);
+        if (!pendingPacketsLock.tryLock(maxWait, TimeUnit.MILLISECONDS)) {
+            throw new TimeoutException("Failed to acquire " + numPending + " pending packets lock");
+        }
+
+        try {
+            return executor.call();
+        } finally {
+            pendingPacketsLock.unlock();
+        }
+    }
+
     protected void doKexNegotiation() throws Exception {
         if (kexState.compareAndSet(KexState.DONE, KexState.RUN)) {
             sendKexInit();
@@ -669,9 +707,10 @@ public abstract class AbstractSession extends SessionHelper {
         KeyExchangeFactory kexFactory = NamedResource.findByName(
                 kexAlgorithm, String.CASE_INSENSITIVE_ORDER, kexFactories);
         ValidateUtils.checkNotNull(kexFactory, "Unknown negotiated KEX algorithm: %s", kexAlgorithm);
-        synchronized (pendingPackets) {
+        executeUnderPendingPacketsLock(0L, () -> {
             kex = kexFactory.createKeyExchange(this);
-        }
+            return kex;
+        });
 
         byte[] v_s = serverVersion.getBytes(StandardCharsets.UTF_8);
         byte[] v_c = clientVersion.getBytes(StandardCharsets.UTF_8);
@@ -707,12 +746,13 @@ public abstract class AbstractSession extends SessionHelper {
 
         signalSessionEvent(SessionListener.Event.KeyEstablished);
 
-        Collection<? extends Map.Entry<? extends SshFutureListener<IoWriteFuture>, IoWriteFuture>> pendingWrites;
-        synchronized (pendingPackets) {
-            pendingWrites = sendPendingPackets(pendingPackets);
-            kex = null; // discard and GC since KEX is completed
-            kexState.set(KexState.DONE);
-        }
+        Collection<? extends Map.Entry<? extends SshFutureListener<IoWriteFuture>, IoWriteFuture>> pendingWrites
+                = executeUnderPendingPacketsLock(FactoryManager.DEFAULT_NIO2_MIN_WRITE_TIMEOUT, () -> {
+                    List<Map.Entry<PendingWriteFuture, IoWriteFuture>> result = sendPendingPackets(pendingPackets);
+                    kex = null; // discard and GC since KEX is completed
+                    kexState.set(KexState.DONE);
+                    return result;
+                });
 
         int pendingCount = pendingWrites.size();
         if (pendingCount > 0) {
@@ -734,7 +774,7 @@ public abstract class AbstractSession extends SessionHelper {
         }
     }
 
-    protected List<SimpleImmutableEntry<PendingWriteFuture, IoWriteFuture>> sendPendingPackets(
+    protected List<Map.Entry<PendingWriteFuture, IoWriteFuture>> sendPendingPackets(
             Queue<PendingWriteFuture> packetsQueue)
             throws IOException {
         if (GenericUtils.isEmpty(packetsQueue)) {
@@ -742,7 +782,7 @@ public abstract class AbstractSession extends SessionHelper {
         }
 
         int numPending = packetsQueue.size();
-        List<SimpleImmutableEntry<PendingWriteFuture, IoWriteFuture>> pendingWrites = new ArrayList<>(numPending);
+        List<Map.Entry<PendingWriteFuture, IoWriteFuture>> pendingWrites = new ArrayList<>(numPending);
         synchronized (encodeLock) {
             for (PendingWriteFuture future = packetsQueue.poll();
                  future != null;
@@ -872,10 +912,11 @@ public abstract class AbstractSession extends SessionHelper {
      * Checks if key-exchange is done - if so, or the packet is related to the key-exchange protocol, then allows the
      * packet to go through, otherwise enqueues it to be sent when key-exchange completed
      *
-     * @param  buffer The {@link Buffer} containing the packet to be sent
-     * @return        A {@link PendingWriteFuture} if enqueued, {@code null} if packet can go through.
+     * @param  buffer      The {@link Buffer} containing the packet to be sent
+     * @return             A {@link PendingWriteFuture} if enqueued, {@code null} if packet can go through.
+     * @throws IOException If failed to enqueue
      */
-    protected PendingWriteFuture enqueuePendingPacket(Buffer buffer) {
+    protected PendingWriteFuture enqueuePendingPacket(Buffer buffer) throws IOException {
         if (KexState.DONE.equals(kexState.get())) {
             return null;
         }
@@ -887,20 +928,33 @@ public abstract class AbstractSession extends SessionHelper {
         }
 
         String cmdName = SshConstants.getCommandMessageName(cmd);
+        AtomicInteger numPending = new AtomicInteger();
         PendingWriteFuture future;
-        int numPending;
-        synchronized (pendingPackets) {
-            if (KexState.DONE.equals(kexState.get())) {
-                return null;
-            }
+        try {
+            future = executeUnderPendingPacketsLock(0L, () -> {
+                if (KexState.DONE.equals(kexState.get())) {
+                    return null;
+                }
+
+                PendingWriteFuture pending = new PendingWriteFuture(cmdName, buffer);
+                pendingPackets.add(pending);
+                numPending.set(pendingPackets.size());
+                return pending;
+            });
+        } catch (Exception e) {
+            log.error("enqueuePendingPacket(" + this + ")[" + cmdName + "] failed to generate future", e);
 
-            future = new PendingWriteFuture(cmdName, buffer);
-            pendingPackets.add(future);
-            numPending = pendingPackets.size();
+            if (e instanceof IOException) {
+                throw (IOException) e;
+            } else if (e instanceof RuntimeException) {
+                throw (RuntimeException) e;
+            } else {
+                throw new RuntimeSshException(e);
+            }
         }
 
         if (log.isDebugEnabled()) {
-            if (numPending == 1) {
+            if (numPending.get() == 1) {
                 log.debug("enqueuePendingPacket({})[{}] Start flagging packets as pending until key exchange is done", this,
                         cmdName);
             } else {


[mina-sshd] 01/17: Upgraded Checkstyle version to 8.32

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 8c9b9a2cb26fd2671e34e4a63a6514ca2b2bd588
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 06:59:28 2020 +0300

    Upgraded Checkstyle version to 8.32
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 9f4bb97..e6f370a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -845,7 +845,7 @@
                         <dependency>
                             <groupId>com.puppycrawl.tools</groupId>
                             <artifactId>checkstyle</artifactId>
-                            <version>8.31</version>
+                            <version>8.32</version>
                             <exclusions>
                                 <!-- MCHECKSTYLE-156 -->
                                 <exclusion>


[mina-sshd] 14/17: Upgraded Maven javadoc plugin version to 3.2.0

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit f4aa39710cf05d8d2094beb060161f27fa480843
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:18:58 2020 +0300

    Upgraded Maven javadoc plugin version to 3.2.0
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 2c0cfec..3249116 100644
--- a/pom.xml
+++ b/pom.xml
@@ -759,7 +759,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-javadoc-plugin</artifactId>
-                    <version>3.1.1</version>
+                    <version>3.2.0</version>
                     <configuration>
                         <additionalOptions>-Xdoclint:-missing</additionalOptions>
                         <encoding>${project.build.sourceEncoding}</encoding>


[mina-sshd] 10/17: Upgraded Maven ANT plugin version to 3.0.0

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 9d92a4a9df6c76705e5d83a9865d37b2dc4bea73
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:15:43 2020 +0300

    Upgraded Maven ANT plugin version to 3.0.0
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 88ca38c..bc8f6e6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1011,7 +1011,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-antrun-plugin</artifactId>
-                    <version>1.8</version>
+                    <version>3.0.0</version>
                     <dependencies>
                         <dependency>
                             <groupId>org.apache.ant</groupId>


[mina-sshd] 08/17: Upgraded Spring Integration version to 5.3.0

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit bff5387a9771a09739733e6f7a5a1fdb8263c6ed
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:13:28 2020 +0300

    Upgraded Spring Integration version to 5.3.0
---
 sshd-spring-sftp/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sshd-spring-sftp/pom.xml b/sshd-spring-sftp/pom.xml
index 1032ec3..888a850 100644
--- a/sshd-spring-sftp/pom.xml
+++ b/sshd-spring-sftp/pom.xml
@@ -32,7 +32,7 @@
 
     <properties>
         <projectRoot>${project.basedir}/..</projectRoot>
-        <spring.integration.version>5.2.5.RELEASE</spring.integration.version>
+        <spring.integration.version>5.3.0.RELEASE</spring.integration.version>
     </properties>
 
     <dependencyManagement>


[mina-sshd] 13/17: Upgraded Maven enforcer plugin version to 3.0.0-M3

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 2ef5f5fac779f1f1bcbf3c13b70fb0a0a3da8385
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:17:48 2020 +0300

    Upgraded Maven enforcer plugin version to 3.0.0-M3
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index f369079..2c0cfec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1175,7 +1175,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-enforcer-plugin</artifactId>
-                <version>3.0.0-M2</version>
+                <version>3.0.0-M3</version>
                 <executions>
                     <execution>
                         <id>enforce-versions</id>


[mina-sshd] 15/17: Upgraded Maven remote resources plugin version to 1.7.0

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 9389943e1520f55b622556a3f2be55df19c219fd
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:19:28 2020 +0300

    Upgraded Maven remote resources plugin version to 1.7.0
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 3249116..8103cd9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1271,7 +1271,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-remote-resources-plugin</artifactId>
-                <version>1.6.0</version>
+                <version>1.7.0</version>
                 <executions>
                     <execution>
                         <goals>


[mina-sshd] 09/17: Upgraded Netty version to 4.1.50

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 966b609f877d3edf1a23c366af0226faf2b23fa4
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:14:20 2020 +0300

    Upgraded Netty version to 4.1.50
---
 sshd-netty/pom.xml | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/sshd-netty/pom.xml b/sshd-netty/pom.xml
index 52d6bcf..8fa432c 100644
--- a/sshd-netty/pom.xml
+++ b/sshd-netty/pom.xml
@@ -33,9 +33,20 @@
 
     <properties>
         <projectRoot>${project.basedir}/..</projectRoot>
-        <netty.version>4.1.48.Final</netty.version>
     </properties>
 
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>io.netty</groupId>
+                <artifactId>netty-bom</artifactId>
+                <version>4.1.50.Final</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
     <dependencies>
         <dependency>
             <groupId>org.apache.sshd</groupId>
@@ -45,12 +56,10 @@
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-transport</artifactId>
-            <version>${netty.version}</version>
         </dependency>
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-handler</artifactId>
-            <version>${netty.version}</version>
         </dependency>
 
         <!-- test dependencies -->


[mina-sshd] 02/17: Upgraded Groovy version to 2.5.11

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 6e40b2363d817c7b8be1a02c39fd5e2c062b2173
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:04:32 2020 +0300

    Upgraded Groovy version to 2.5.11
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index e6f370a..914fb64 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
         <gmaven.plugin.version>2.1.1</gmaven.plugin.version>
         <groovy.major.version>2</groovy.major.version>
         <groovy.minor.version>5</groovy.minor.version>
-        <groovy.release.version>10</groovy.release.version>
+        <groovy.release.version>11</groovy.release.version>
         <groovy.compliance.level>2.0</groovy.compliance.level>
         <groovy.version>${groovy.major.version}.${groovy.minor.version}.${groovy.release.version}</groovy.version>
 


[mina-sshd] 04/17: Upgraded Spring Core version to 5.2.6

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 9cad2939d59281c4a30c88912cfd4229fad73f10
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:09:32 2020 +0300

    Upgraded Spring Core version to 5.2.6
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 8a95193..8bbde34 100644
--- a/pom.xml
+++ b/pom.xml
@@ -114,7 +114,7 @@
             -->
         <bouncycastle.version>1.64</bouncycastle.version>
         <slf4j.version>1.7.30</slf4j.version>
-        <spring.version>5.2.5.RELEASE</spring.version>
+        <spring.version>5.2.6.RELEASE</spring.version>
         <jgit.version>5.7.0.202003110725-r</jgit.version>
         <junit.version>4.13</junit.version>
         <bytebuddy.version>1.10.10</bytebuddy.version>


[mina-sshd] 05/17: Upgraded PMD version to 6.23.0

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit d1df42e6446ee606259fa29abbc056adb59e17d1
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:10:12 2020 +0300

    Upgraded PMD version to 6.23.0
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 8bbde34..d8f4a9a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -127,7 +127,7 @@
         -->
         <plexus.archiver.version>4.1.0</plexus.archiver.version>
         <!-- See https://pmd.github.io/ for available latest version -->
-        <pmd.version>6.22.0</pmd.version>
+        <pmd.version>6.23.0</pmd.version>
 
         <sshd.tests.timeout.factor>1.0</sshd.tests.timeout.factor>
         <sshd.tests.rerun.count>2</sshd.tests.rerun.count>


[mina-sshd] 07/17: Upraded testcontainers version to 1.14.1

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 7a23ed13a6ac02687aafd7836af9376cd3d91e27
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:12:31 2020 +0300

    Upraded testcontainers version to 1.14.1
---
 sshd-sftp/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sshd-sftp/pom.xml b/sshd-sftp/pom.xml
index 4cf78e3..f581b1d 100644
--- a/sshd-sftp/pom.xml
+++ b/sshd-sftp/pom.xml
@@ -103,7 +103,7 @@
                 <groupId>org.testcontainers</groupId>
                 <artifactId>testcontainers-bom</artifactId>
                 <type>pom</type>
-                <version>1.14.0</version>
+                <version>1.14.1</version>
                 <scope>import</scope>
             </dependency>
         </dependencies>


[mina-sshd] 11/17: Upgraded Maven assembly plugin version to 3.3.0

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit 0f28c29b60c2e0a5d116c3fa8432af4c271787e4
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:16:25 2020 +0300

    Upgraded Maven assembly plugin version to 3.3.0
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index bc8f6e6..f2d615e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1318,7 +1318,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-assembly-plugin</artifactId>
-                <version>3.2.0</version>
+                <version>3.3.0</version>
                 <executions>
                     <execution>
                         <id>source-release-assembly</id>


[mina-sshd] 12/17: Upgraded Maven dependency plugin version to 3.1.2

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit d23d80d59ffed0d8bbb20997fbd9471c069e16be
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:17:06 2020 +0300

    Upgraded Maven dependency plugin version to 3.1.2
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index f2d615e..f369079 100644
--- a/pom.xml
+++ b/pom.xml
@@ -998,7 +998,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-dependency-plugin</artifactId>
-                    <version>3.1.1</version>
+                    <version>3.1.2</version>
                     <dependencies>
                         <dependency>
                             <groupId>org.codehaus.plexus</groupId>


[mina-sshd] 03/17: Upgraded ByteBuddy version to 1.10.10

Posted by lg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-966
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit ab2dc90b4114eb0a4ff3ef2c2cb379760e939e17
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri May 15 07:08:11 2020 +0300

    Upgraded ByteBuddy version to 1.10.10
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 914fb64..8a95193 100644
--- a/pom.xml
+++ b/pom.xml
@@ -117,7 +117,7 @@
         <spring.version>5.2.5.RELEASE</spring.version>
         <jgit.version>5.7.0.202003110725-r</jgit.version>
         <junit.version>4.13</junit.version>
-        <bytebuddy.version>1.10.9</bytebuddy.version>
+        <bytebuddy.version>1.10.10</bytebuddy.version>
 
         <surefire.plugin.version>2.22.2</surefire.plugin.version>
         <maven.archiver.version>3.5.0</maven.archiver.version>