[SSHD-838] Implement initial IoServiceEventListener in Nio2ServiceFactory

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

Branch: refs/heads/master
Commit: 909e7ac08ed5c0aa0db7ad00c753aec8d3aeb887
Parents: 881e9db
Author: Goldstein Lyor <[email protected]>
Authored: Sun Aug 5 15:08:15 2018 +0300
Committer: Lyor Goldstein <[email protected]>
Committed: Sun Aug 5 19:35:53 2018 +0300

----------------------------------------------------------------------
 README.md                                       |   6 +
 .../java/org/apache/sshd/cli/CliSupport.java    |  73 ++++++++++-
 .../sshd/cli/client/SshClientCliSupport.java    |   6 +-
 .../apache/sshd/cli/server/SshServerMain.java   |   2 +-
 .../apache/sshd/cli/server/SshFsMounter.java    |   4 +-
 .../org/apache/sshd/common/FactoryManager.java  |   2 +
 .../common/helpers/AbstractFactoryManager.java  |  12 ++
 .../common/io/AbstractIoServiceFactory.java     |  25 +++-
 .../org/apache/sshd/common/io/IoService.java    |   2 +-
 .../sshd/common/io/IoServiceEventListener.java  |  88 ++++++++++++++
 .../io/IoServiceEventListenerManager.java       |  28 +++++
 .../apache/sshd/common/io/IoServiceFactory.java |   2 +-
 .../sshd/common/io/nio2/Nio2Acceptor.java       |  34 +++++-
 .../sshd/common/io/nio2/Nio2Connector.java      | 120 ++++++++++++-------
 .../apache/sshd/common/io/nio2/Nio2Service.java |  12 ++
 .../sshd/common/io/nio2/Nio2ServiceFactory.java |   4 +-
 .../io/nio2/Nio2ServiceFactoryFactory.java      |   9 +-
 .../apache/sshd/common/io/mina/MinaService.java |  13 ++
 .../sshd/common/io/mina/MinaServiceFactory.java |   4 +-
 .../io/mina/MinaServiceFactoryFactory.java      |   7 +-
 .../org/apache/sshd/netty/NettyIoAcceptor.java  |   5 +-
 .../org/apache/sshd/netty/NettyIoConnector.java |   4 +-
 .../org/apache/sshd/netty/NettyIoService.java   |  26 +++-
 .../sshd/netty/NettyIoServiceFactory.java       |  13 ++
 .../netty/NettyIoServiceFactoryFactory.java     |   7 +-
 25 files changed, 427 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index a44b48d..251370a 100644
--- a/README.md
+++ b/README.md
@@ -1134,6 +1134,12 @@ In general, event listeners are **cumulative** - e.g., 
any channel event listene
 
 ```
 
+### `IoServiceEventListener`
+
+This listener provides low-level events regarding connection establishment (by 
the client) or acceptance (by the server). The listener is registered
+on the `IoServiceFactory` via the `FactoryManager`-s (i.e., 
`SshClient/Server#setIoServiceEventListener`). Unlike other listeners defined 
in this
+section, it is **not cumulative** - i.e., one can `setIoServiceEventListener` 
but not `addIoServiceEventListener` - thus **replacing** any previously
+registered listener.
 
 ### `SessionListener`
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java
----------------------------------------------------------------------
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java 
b/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java
index 942fcf3..27c6d96 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java
@@ -18,10 +18,19 @@
  */
 package org.apache.sshd.cli;
 
+import java.io.IOException;
 import java.io.PrintStream;
+import java.net.SocketAddress;
+import java.util.Map;
+import java.util.Objects;
 
+import org.apache.sshd.common.config.LogLevelValue;
+import org.apache.sshd.common.config.SshConfigFileReader;
 import org.apache.sshd.common.helpers.AbstractFactoryManager;
 import org.apache.sshd.common.io.BuiltinIoServiceFactoryFactories;
+import org.apache.sshd.common.io.IoAcceptor;
+import org.apache.sshd.common.io.IoConnector;
+import org.apache.sshd.common.io.IoServiceEventListener;
 import org.apache.sshd.common.io.IoServiceFactoryFactory;
 import org.apache.sshd.common.util.GenericUtils;
 
@@ -87,13 +96,75 @@ public abstract class CliSupport {
         return factory;
     }
 
-    public static <M extends AbstractFactoryManager> M setupIoServiceFactory(M 
manager, PrintStream stderr, String... args) {
+    public static <M extends AbstractFactoryManager> M setupIoServiceFactory(
+            M manager, Map<String, ?> options, PrintStream stdout, PrintStream 
stderr, String... args) {
         BuiltinIoServiceFactoryFactories factory = 
resolveIoServiceFactory(stderr, args);
         if (factory == null) {
             return null;
         }
 
         manager.setIoServiceFactoryFactory(factory.create());
+
+        String levelValue = (options == null) ? null : 
Objects.toString(options.get(SshConfigFileReader.LOG_LEVEL_CONFIG_PROP), null);
+        if (GenericUtils.isEmpty(levelValue)) {
+            return manager;
+        }
+
+        LogLevelValue level = LogLevelValue.fromName(levelValue);
+        if (level == null) {
+            throw new IllegalArgumentException("Unknown " + 
SshConfigFileReader.LOG_LEVEL_CONFIG_PROP + " option value: " + levelValue);
+        }
+
+        if ((level != LogLevelValue.FATAL) && (level != LogLevelValue.ERROR) 
&& (level != LogLevelValue.INFO)) {
+            return manager;
+        }
+
+        manager.setIoServiceEventListener(new IoServiceEventListener() {
+            private final PrintStream out = (level == LogLevelValue.INFO) ? 
stdout : stderr;
+
+            @Override
+            public void connectionEstablished(
+                    IoConnector connector, SocketAddress local, SocketAddress 
remote)
+                        throws IOException {
+                out.append("Connection established via 
").append(Objects.toString(connector))
+                    .append("- local=").append(Objects.toString(local))
+                    .append(", remote=").append(Objects.toString(remote))
+                    .println();
+            }
+
+            @Override
+            public void abortEstablishedConnection(
+                    IoConnector connector, SocketAddress local, SocketAddress 
remote, Throwable reason)
+                        throws IOException {
+                out.append("Abort established connection 
").append(Objects.toString(connector))
+                    .append(" - local=").append(Objects.toString(local))
+                    .append(", remote=").append(Objects.toString(remote))
+                    .append(": 
(").append(reason.getClass().getSimpleName()).append(')')
+                    .append(" ").println(reason.getMessage());
+                reason.printStackTrace(out);
+            }
+
+            @Override
+            public void connectionAccepted(IoAcceptor acceptor, SocketAddress 
local, SocketAddress remote)
+                    throws IOException {
+                out.append("Connection accepted via 
").append(Objects.toString(acceptor))
+                    .append(" - local=").append(Objects.toString(local))
+                    .append(", remote=").append(Objects.toString(remote))
+                    .println();
+            }
+
+            @Override
+            public void abortAcceptedConnection(
+                    IoAcceptor acceptor, SocketAddress local, SocketAddress 
remote, Throwable reason)
+                        throws IOException {
+                out.append("Abort accepted connection 
").append(Objects.toString(acceptor))
+                    .append(" - local=").append(Objects.toString(local))
+                    .append(", remote=").append(Objects.toString(remote))
+                    .append(": 
(").append(reason.getClass().getSimpleName()).append(')')
+                    .append(" ").println(reason.getMessage());
+                reason.printStackTrace(out);
+            }
+        });
         return manager;
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java
----------------------------------------------------------------------
diff --git 
a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java 
b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java
index 35d8717..0d7d2f5 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java
@@ -268,8 +268,8 @@ public abstract class SshClientCliSupport extends 
CliSupport {
         }
     }
 
-    public static SshClient setupDefaultClient(PrintStream stderr, String... 
args) {
-        return setupIoServiceFactory(SshClient.setUpDefaultClient(), 
System.err, args);
+    public static SshClient setupDefaultClient(Map<String, ?> options, 
PrintStream stdout, PrintStream stderr, String... args) {
+        return setupIoServiceFactory(SshClient.setUpDefaultClient(), options, 
stdout, stderr, args);
     }
 
     // returns null if error encountered
@@ -305,7 +305,7 @@ public abstract class SshClientCliSupport extends 
CliSupport {
             }
         }
 
-        SshClient client = setupDefaultClient(stderr, args);
+        SshClient client = setupDefaultClient(options, stdout, stderr, args);
         if (client == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
----------------------------------------------------------------------
diff --git 
a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java 
b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
index b9f6d1e..0740d65 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
@@ -146,7 +146,7 @@ public class SshServerMain extends SshServerCliSupport {
             }
         }
 
-        SshServer sshd = error ? null : 
setupIoServiceFactory(SshServer.setUpDefaultServer(), System.err, args);
+        SshServer sshd = error ? null : 
setupIoServiceFactory(SshServer.setUpDefaultServer(), options, System.out, 
System.err, args);
         if (sshd == null) {
             error = true;
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
----------------------------------------------------------------------
diff --git 
a/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java 
b/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
index 4fe1d99..51596b1 100644
--- a/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
+++ b/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
@@ -283,6 +283,7 @@ public final class SshFsMounter extends SshServerCliSupport 
{
                     error = true;
                     break;
                 }
+
                 String opt = args[++i];
                 int idx = opt.indexOf('=');
                 if (idx <= 0) {
@@ -294,7 +295,8 @@ public final class SshFsMounter extends SshServerCliSupport 
{
             }
         }
 
-        SshServer sshd = error ? null : 
setupIoServiceFactory(Utils.setupTestServer(SshFsMounter.class), System.err, 
args);
+        SshServer sshd = error ? null : setupIoServiceFactory(
+            Utils.setupTestServer(SshFsMounter.class), options, System.out, 
System.err, args);
         if (sshd == null) {
             error = true;
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java 
b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
index 50f4a54..31f0de6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
@@ -30,6 +30,7 @@ import 
org.apache.sshd.common.channel.throttle.ChannelStreamPacketWriterResolver
 import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.forward.ForwardingFilterFactory;
 import org.apache.sshd.common.forward.PortForwardingEventListenerManager;
+import org.apache.sshd.common.io.IoServiceEventListenerManager;
 import org.apache.sshd.common.io.IoServiceFactory;
 import org.apache.sshd.common.kex.KexFactoryManager;
 import org.apache.sshd.common.random.Random;
@@ -56,6 +57,7 @@ public interface FactoryManager
                 ChannelStreamPacketWriterResolverManager,
                 UnknownChannelReferenceHandlerManager,
                 PortForwardingEventListenerManager,
+                IoServiceEventListenerManager,
                 AttributeStore,
                 PropertyResolver {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java
index a05fe65..7dd7f86 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java
@@ -46,6 +46,7 @@ import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.forward.ForwardingFilterFactory;
 import org.apache.sshd.common.forward.PortForwardingEventListener;
 import org.apache.sshd.common.io.DefaultIoServiceFactoryFactory;
+import org.apache.sshd.common.io.IoServiceEventListener;
 import org.apache.sshd.common.io.IoServiceFactory;
 import org.apache.sshd.common.io.IoServiceFactoryFactory;
 import org.apache.sshd.common.kex.AbstractKexFactoryManager;
@@ -92,6 +93,7 @@ public abstract class AbstractFactoryManager extends 
AbstractKexFactoryManager i
     private ReservedSessionMessagesHandler reservedSessionMessagesHandler;
     private ChannelStreamPacketWriterResolver 
channelStreamPacketWriterResolver;
     private UnknownChannelReferenceHandler unknownChannelReferenceHandler;
+    private IoServiceEventListener eventListener;
 
     protected AbstractFactoryManager() {
         ClassLoader loader = getClass().getClassLoader();
@@ -119,6 +121,16 @@ public abstract class AbstractFactoryManager extends 
AbstractKexFactoryManager i
     }
 
     @Override
+    public IoServiceEventListener getIoServiceEventListener() {
+        return eventListener;
+    }
+
+    @Override
+    public void setIoServiceEventListener(IoServiceEventListener listener) {
+        eventListener = listener;
+    }
+
+    @Override
     public Factory<Random> getRandomFactory() {
         return randomFactory;
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java
index b15262f..97e2bf0 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java
@@ -35,12 +35,14 @@ public abstract class AbstractIoServiceFactory
                 extends AbstractCloseable
                 implements IoServiceFactory, FactoryManagerHolder, 
ExecutorServiceCarrier {
 
+    private IoServiceEventListener eventListener;
     private final FactoryManager manager;
     private final CloseableExecutorService executor;
 
     protected AbstractIoServiceFactory(FactoryManager factoryManager, 
CloseableExecutorService executorService) {
-        manager = Objects.requireNonNull(factoryManager);
-        executor = Objects.requireNonNull(executorService);
+        manager = Objects.requireNonNull(factoryManager, "No factory manager 
provided");
+        executor = Objects.requireNonNull(executorService, "No executor 
service provided");
+        eventListener = factoryManager.getIoServiceEventListener();
     }
 
     @Override
@@ -54,6 +56,16 @@ public abstract class AbstractIoServiceFactory
     }
 
     @Override
+    public IoServiceEventListener getIoServiceEventListener() {
+        return eventListener;
+    }
+
+    @Override
+    public void setIoServiceEventListener(IoServiceEventListener listener) {
+        eventListener = listener;
+    }
+
+    @Override
     protected void doCloseImmediately() {
         try {
             CloseableExecutorService service = getExecutorService();
@@ -73,6 +85,15 @@ public abstract class AbstractIoServiceFactory
         }
     }
 
+    protected <S extends IoService> S autowireCreatedService(S service) {
+        if (service == null) {
+            return service;
+        }
+
+        service.setIoServiceEventListener(getIoServiceEventListener());
+        return service;
+    }
+
     public static int getNioWorkers(FactoryManager manager) {
         int nb = manager.getIntProperty(FactoryManager.NIO_WORKERS, 
FactoryManager.DEFAULT_NIO_WORKERS);
         if (nb > 0) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java
index 69dcdee..d6fcef3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java
@@ -25,7 +25,7 @@ import org.apache.sshd.common.Closeable;
 /**
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
-public interface IoService extends Closeable {
+public interface IoService extends Closeable, IoServiceEventListenerManager {
     /**
      * Socket reuse address.
      * See {@link java.net.StandardSocketOptions#SO_REUSEADDR}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceEventListener.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceEventListener.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceEventListener.java
new file mode 100644
index 0000000..7018825
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceEventListener.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.io;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+
+import org.apache.sshd.common.util.SshdEventListener;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public interface IoServiceEventListener extends SshdEventListener {
+    /**
+     * Called when a new connection has been created to a remote peer - 
<u>before</u> it was
+     * converted into a session
+     *
+     * @param connector The {@link IoConnector} through which the connection 
was established
+     * @param local The local connection endpoint
+     * @param remote The remote connection endpoint
+     * @throws IOException If failed to handle the event - in which case 
connection will be aborted
+     */
+    default void connectionEstablished(IoConnector connector, SocketAddress 
local, SocketAddress remote) throws IOException {
+        // Do nothing
+    }
+
+    /**
+     * Called when a previously established connection has been abnormally 
terminated before it could be
+     * turned into a session
+     *
+     * @param acceptor The {@link IoConnector} through which the connection 
was established
+     * @param local The local connection endpoint
+     * @param remote The remote connection endpoint
+     * @param reason The reason for aborting - may be an exception thrown by
+     * {@link #connectionEstablished(IoConnector, SocketAddress, 
SocketAddress) connectionEstablished}
+     * @throws IOException If failed to handle the event - the exception is 
logged but does not
+     * prevent further connections from being accepted
+     */
+    default void abortEstablishedConnection(IoConnector connector, 
SocketAddress local, SocketAddress remote, Throwable reason) throws IOException 
{
+        // Do nothing
+    }
+
+    /**
+     * Called when a new connection has been accepted from a remote peer - 
<u>before</u> it was
+     * converted into a session
+     *
+     * @param acceptor The {@link IoAcceptor} through which the connection was 
accepted
+     * @param local The local connection endpoint
+     * @param remote The remote connection endpoint
+     * @throws IOException If failed to handle the event - in which case 
connection will be aborted
+     */
+    default void connectionAccepted(IoAcceptor acceptor, SocketAddress local, 
SocketAddress remote) throws IOException {
+        // Do nothing
+    }
+
+    /**
+     * Called when a previously accepted connection has been abnormally 
terminated before it could be
+     * turned into a session
+     *
+     * @param acceptor The {@link IoAcceptor} through which the connection was 
accepted
+     * @param local The local connection endpoint
+     * @param remote The remote connection endpoint
+     * @param reason The reason for aborting - may be an exception thrown by
+     * {@link #connectionAccepted(IoAcceptor, SocketAddress, SocketAddress) 
connectionAccepted}
+     * @throws IOException If failed to handle the event - the exception is 
logged but does not
+     * prevent further connections from being accepted
+     */
+    default void abortAcceptedConnection(IoAcceptor acceptor, SocketAddress 
local, SocketAddress remote, Throwable reason) throws IOException {
+        // Do nothing
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceEventListenerManager.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceEventListenerManager.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceEventListenerManager.java
new file mode 100644
index 0000000..4dcf55e
--- /dev/null
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceEventListenerManager.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.io;
+
+/**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
+ */
+public interface IoServiceEventListenerManager {
+    IoServiceEventListener getIoServiceEventListener();
+
+    void setIoServiceEventListener(IoServiceEventListener listener);
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java
index 6d8c261..d6c110b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java
@@ -23,7 +23,7 @@ import org.apache.sshd.common.Closeable;
 /**
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
-public interface IoServiceFactory extends Closeable {
+public interface IoServiceFactory extends Closeable, 
IoServiceEventListenerManager {
 
     IoConnector createConnector(IoHandler handler);
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
index 1c63b54..0c90ce3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
@@ -36,6 +36,7 @@ import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoHandler;
+import org.apache.sshd.common.io.IoServiceEventListener;
 import org.apache.sshd.common.util.ValidateUtils;
 
 /**
@@ -196,7 +197,14 @@ public class Nio2Acceptor extends Nio2Service implements 
IoAcceptor {
             Nio2Session session = null;
             Long sessionId = null;
             boolean keepAccepting;
+            IoServiceEventListener listener = getIoServiceEventListener();
             try {
+                if (listener != null) {
+                    SocketAddress localAddress = result.getLocalAddress();
+                    SocketAddress remoteAddress = result.getRemoteAddress();
+                    listener.connectionAccepted(Nio2Acceptor.this, 
localAddress, remoteAddress);
+                }
+
                 // Create a session
                 IoHandler handler = getIoHandler();
                 setSocketOptions(result);
@@ -216,6 +224,17 @@ public class Nio2Acceptor extends Nio2Service implements 
IoAcceptor {
 
                 keepAccepting = true;
             } catch (Throwable exc) {
+                if (listener != null) {
+                    try {
+                        SocketAddress localAddress = result.getLocalAddress();
+                        SocketAddress remoteAddress = 
result.getRemoteAddress();
+                        listener.abortAcceptedConnection(Nio2Acceptor.this, 
localAddress, remoteAddress, exc);
+                    } catch (Exception e) {
+                        if (log.isDebugEnabled()) {
+                            log.debug("onCompleted(" + address + ") listener=" 
+ listener + " ignoring abort event exception", e);
+                        }
+                    }
+                }
                 keepAccepting = okToReaccept(exc, address);
 
                 // fail fast the accepted connection
@@ -269,8 +288,9 @@ public class Nio2Acceptor extends Nio2Service implements 
IoAcceptor {
 
         protected boolean okToReaccept(Throwable exc, SocketAddress address) {
             AsynchronousServerSocketChannel channel = channels.get(address);
+            boolean debugEnabled = log.isDebugEnabled();
             if (channel == null) {
-                if (log.isDebugEnabled()) {
+                if (debugEnabled) {
                     log.debug("Caught {} for untracked channel of {}: {}",
                         exc.getClass().getSimpleName(), address, 
exc.getMessage());
                 }
@@ -278,17 +298,19 @@ public class Nio2Acceptor extends Nio2Service implements 
IoAcceptor {
             }
 
             if (disposing.get()) {
-                if (log.isDebugEnabled()) {
+                if (debugEnabled) {
                     log.debug("Caught {} for tracked channel of {} while 
disposing: {}",
                         exc.getClass().getSimpleName(), address, 
exc.getMessage());
                 }
                 return false;
             }
 
-            log.warn("Caught {} while accepting incoming connection from {}: 
{}",
-                exc.getClass().getSimpleName(), address, exc.getMessage());
-            if (log.isDebugEnabled()) {
-                log.debug("Incoming connection from " + address + " failure 
details", exc);
+            if (debugEnabled) {
+                log.debug("Caught {} while accepting incoming connection from 
{}: {}",
+                    exc.getClass().getSimpleName(), address, exc.getMessage());
+            }
+            if (log.isTraceEnabled()) {
+                log.trace("Incoming connection from " + address + " failure 
details", exc);
             }
             return true;
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java
index 2924caf..061795d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java
@@ -28,6 +28,7 @@ import org.apache.sshd.common.future.DefaultSshFuture;
 import org.apache.sshd.common.io.IoConnectFuture;
 import org.apache.sshd.common.io.IoConnector;
 import org.apache.sshd.common.io.IoHandler;
+import org.apache.sshd.common.io.IoServiceEventListener;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.ValidateUtils;
@@ -60,9 +61,9 @@ public class Nio2Connector extends Nio2Service implements 
IoConnector {
                 socket.bind(localAddress);
             }
             Nio2CompletionHandler<Void, Object> completionHandler =
-                    
ValidateUtils.checkNotNull(createConnectionCompletionHandler(future, socket, 
getFactoryManager(), getIoHandler()),
-                                               "No connection completion 
handler created for %s",
-                                               address);
+                
ValidateUtils.checkNotNull(createConnectionCompletionHandler(future, socket, 
getFactoryManager(), getIoHandler()),
+                   "No connection completion handler created for %s",
+                   address);
             socket.connect(address, null, completionHandler);
         } catch (Throwable exc) {
             Throwable t = GenericUtils.peelException(exc);
@@ -110,55 +111,88 @@ public class Nio2Connector extends Nio2Service implements 
IoConnector {
 
     protected Nio2CompletionHandler<Void, Object> 
createConnectionCompletionHandler(
             IoConnectFuture future, AsynchronousSocketChannel socket, 
FactoryManager manager, IoHandler handler) {
-        return new Nio2CompletionHandler<Void, Object>() {
-            @Override
-            @SuppressWarnings("synthetic-access")
-            protected void onCompleted(Void result, Object attachment) {
-                Long sessionId = null;
-                try {
-                    Nio2Session session = createSession(manager, handler, 
socket);
-                    handler.sessionCreated(session);
-                    sessionId = session.getId();
-                    sessions.put(sessionId, session);
-                    future.setSession(session);
-                    if (session.isClosing()) {
-                        try {
-                            handler.sessionClosed(session);
-                        } finally {
-                            unmapSession(sessionId);
-                        }
-                    } else {
-                        session.startReading();
-                    }
-                } catch (Throwable exc) {
-                    Throwable t = GenericUtils.peelException(exc);
-                    boolean debugEnabled = log.isDebugEnabled();
-                    if (debugEnabled) {
-                        log.debug("onCompleted - failed {} to start session: 
{}",
-                                  t.getClass().getSimpleName(), 
t.getMessage());
-                    }
-                    if (log.isTraceEnabled()) {
-                        log.trace("onCompleted - session creation failure 
details", t);
-                    }
+        return new ConnectionCompletionHandler(future, socket, manager, 
handler);
+    }
 
+    protected class ConnectionCompletionHandler extends 
Nio2CompletionHandler<Void, Object> {
+        protected final IoConnectFuture future;
+        protected final AsynchronousSocketChannel socket;
+        protected final FactoryManager manager;
+        protected final IoHandler handler;
+
+        protected ConnectionCompletionHandler(
+                IoConnectFuture future, AsynchronousSocketChannel socket, 
FactoryManager manager, IoHandler handler) {
+            this.future = future;
+            this.socket = socket;
+            this.manager = manager;
+            this.handler = handler;
+        }
+
+        @Override
+        @SuppressWarnings("synthetic-access")
+        protected void onCompleted(Void result, Object attachment) {
+            Long sessionId = null;
+            IoServiceEventListener listener = getIoServiceEventListener();
+            try {
+                if (listener != null) {
+                    SocketAddress local = socket.getLocalAddress();
+                    SocketAddress remote = socket.getRemoteAddress();
+                    listener.connectionEstablished(Nio2Connector.this, local, 
remote);
+                }
+
+                Nio2Session session = createSession(manager, handler, socket);
+                handler.sessionCreated(session);
+                sessionId = session.getId();
+                sessions.put(sessionId, session);
+                future.setSession(session);
+                if (session.isClosing()) {
+                    try {
+                        handler.sessionClosed(session);
+                    } finally {
+                        unmapSession(sessionId);
+                    }
+                } else {
+                    session.startReading();
+                }
+            } catch (Throwable exc) {
+                Throwable t = GenericUtils.peelException(exc);
+                boolean debugEnabled = log.isDebugEnabled();
+                if (listener != null) {
                     try {
-                        socket.close();
-                    } catch (IOException err) {
+                        SocketAddress localAddress = socket.getLocalAddress();
+                        SocketAddress remoteAddress = 
socket.getRemoteAddress();
+                        
listener.abortEstablishedConnection(Nio2Connector.this, localAddress, 
remoteAddress, t);
+                    } catch (Exception e) {
                         if (debugEnabled) {
-                            log.debug("onCompleted - failed {} to close 
socket: {}", err.getClass().getSimpleName(), err.getMessage());
+                            log.debug("onCompleted() listener=" + listener + " 
ignoring abort event exception", e);
                         }
                     }
+                }
 
-                    future.setException(t);
-                    unmapSession(sessionId);
+                if (debugEnabled) {
+                    log.debug("onCompleted - failed {} to start session: {}", 
t.getClass().getSimpleName(), t.getMessage());
+                }
+                if (log.isTraceEnabled()) {
+                    log.trace("onCompleted - session creation failure 
details", t);
                 }
-            }
 
-            @Override
-            protected void onFailed(Throwable exc, Object attachment) {
-                future.setException(exc);
+                try {
+                    socket.close();
+                } catch (IOException err) {
+                    if (debugEnabled) {
+                        log.debug("onCompleted - failed {} to close socket: 
{}", err.getClass().getSimpleName(), err.getMessage());
+                    }
+                }
+
+                future.setException(t);
+                unmapSession(sessionId);
             }
-        };
+        }
+
+        @Override
+        protected void onFailed(Throwable exc, Object attachment) {
+            future.setException(exc);
+        }
     }
 
     protected Nio2Session createSession(FactoryManager manager, IoHandler 
handler, AsynchronousSocketChannel socket) throws Throwable {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
index d0983ff..b340ec8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
@@ -39,6 +39,7 @@ import org.apache.sshd.common.FactoryManagerHolder;
 import org.apache.sshd.common.PropertyResolver;
 import org.apache.sshd.common.io.IoHandler;
 import org.apache.sshd.common.io.IoService;
+import org.apache.sshd.common.io.IoServiceEventListener;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
@@ -66,6 +67,7 @@ public abstract class Nio2Service extends 
AbstractInnerCloseable implements IoSe
     private final FactoryManager manager;
     private final IoHandler handler;
     private final AsynchronousChannelGroup group;
+    private IoServiceEventListener eventListener;
 
     protected Nio2Service(FactoryManager manager, IoHandler handler, 
AsynchronousChannelGroup group) {
         if (log.isTraceEnabled()) {
@@ -77,6 +79,16 @@ public abstract class Nio2Service extends 
AbstractInnerCloseable implements IoSe
         this.sessions = new ConcurrentHashMap<>();
     }
 
+    @Override
+    public IoServiceEventListener getIoServiceEventListener() {
+        return eventListener;
+    }
+
+    @Override
+    public void setIoServiceEventListener(IoServiceEventListener listener) {
+        eventListener = listener;
+    }
+
     protected AsynchronousChannelGroup getChannelGroup() {
         return group;
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
index 80c047f..493f2c5 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
@@ -54,12 +54,12 @@ public class Nio2ServiceFactory extends 
AbstractIoServiceFactory {
 
     @Override
     public IoConnector createConnector(IoHandler handler) {
-        return new Nio2Connector(getFactoryManager(), handler, group);
+        return autowireCreatedService(new Nio2Connector(getFactoryManager(), 
handler, group));
     }
 
     @Override
     public IoAcceptor createAcceptor(IoHandler handler) {
-        return new Nio2Acceptor(getFactoryManager(), handler, group);
+        return autowireCreatedService(new Nio2Acceptor(getFactoryManager(), 
handler, group));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java
index 478f152..935fd92 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java
@@ -28,18 +28,17 @@ import org.apache.sshd.common.io.IoServiceFactory;
 import org.apache.sshd.common.util.threads.CloseableExecutorService;
 
 /**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
 public class Nio2ServiceFactoryFactory extends AbstractIoServiceFactoryFactory 
{
-
     public Nio2ServiceFactoryFactory() {
         this(null);
     }
 
     /**
-     * @param executors      The {@link CloseableExecutorService} to use for 
spawning threads.
-     *                       If {@code null} then an internal service is 
allocated - in which case it
-     *                       is automatically shutdown regardless of the value 
of the <tt>shutdownOnExit</tt>
-     *                       parameter value
+     * @param executors The {@link CloseableExecutorService} to use for 
spawning threads.
+     * If {@code null} then an internal service is allocated - in which case it
+     * is automatically shutdown
      */
     public Nio2ServiceFactoryFactory(Factory<CloseableExecutorService> 
executors) {
         super(executors);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
----------------------------------------------------------------------
diff --git 
a/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaService.java 
b/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
index 2a0c2ec..c183795 100644
--- a/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
+++ b/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
@@ -35,6 +35,7 @@ import org.apache.mina.transport.socket.SocketSessionConfig;
 import org.apache.mina.transport.socket.nio.NioSession;
 import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.io.IoServiceEventListener;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.Readable;
 import org.apache.sshd.common.util.closeable.AbstractCloseable;
@@ -48,12 +49,24 @@ public abstract class MinaService extends AbstractCloseable 
implements org.apach
     protected final IoProcessor<NioSession> ioProcessor;
     protected IoSessionConfig sessionConfig;
 
+    private IoServiceEventListener eventListener;
+
     public MinaService(FactoryManager manager, 
org.apache.sshd.common.io.IoHandler handler, IoProcessor<NioSession> 
ioProcessor) {
         this.manager = Objects.requireNonNull(manager, "No factory manager 
provided");
         this.handler = Objects.requireNonNull(handler, "No IoHandler 
provided");
         this.ioProcessor = Objects.requireNonNull(ioProcessor, "No IoProcessor 
provided");
     }
 
+    @Override
+    public IoServiceEventListener getIoServiceEventListener() {
+        return eventListener;
+    }
+
+    @Override
+    public void setIoServiceEventListener(IoServiceEventListener listener) {
+        eventListener = listener;
+    }
+
     protected abstract IoService getIoService();
 
     public void dispose() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
 
b/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
index 2a4299a..6585fcb 100644
--- 
a/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
+++ 
b/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
@@ -46,11 +46,11 @@ public class MinaServiceFactory extends 
AbstractIoServiceFactory {
 
     @Override
     public IoConnector createConnector(IoHandler handler) {
-        return new MinaConnector(getFactoryManager(), handler, ioProcessor);
+        return autowireCreatedService(new MinaConnector(getFactoryManager(), 
handler, ioProcessor));
     }
 
     @Override
     public IoAcceptor createAcceptor(IoHandler handler) {
-        return new MinaAcceptor(getFactoryManager(), handler, ioProcessor);
+        return autowireCreatedService(new MinaAcceptor(getFactoryManager(), 
handler, ioProcessor));
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java
 
b/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java
index 901bf3e..fdd190f 100644
--- 
a/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java
+++ 
b/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java
@@ -25,6 +25,9 @@ import org.apache.sshd.common.io.IoServiceFactory;
 import org.apache.sshd.common.util.threads.CloseableExecutorService;
 
 /**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
 public class MinaServiceFactoryFactory extends AbstractIoServiceFactoryFactory 
{
     public MinaServiceFactoryFactory() {
@@ -32,8 +35,8 @@ public class MinaServiceFactoryFactory extends 
AbstractIoServiceFactoryFactory {
     }
 
     /**
-     * @param factory      The {@link CloseableExecutorService} factory to use 
for spawning threads.
-     *                     If {@code null} then an internal service is 
allocated.
+     * @param factory The {@link CloseableExecutorService} factory to use for 
spawning threads.
+     * If {@code null} then an internal service is allocated.
      */
     public MinaServiceFactoryFactory(Factory<CloseableExecutorService> 
factory) {
         super(factory);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoAcceptor.java
----------------------------------------------------------------------
diff --git 
a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoAcceptor.java 
b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoAcceptor.java
index 7f710e1..05e6dcc 100644
--- a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoAcceptor.java
+++ b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoAcceptor.java
@@ -58,11 +58,10 @@ public class NettyIoAcceptor extends NettyIoService 
implements IoAcceptor {
     protected final ServerBootstrap bootstrap = new ServerBootstrap();
     protected final DefaultCloseFuture closeFuture = new 
DefaultCloseFuture(toString(), lock);
     protected final Map<SocketAddress, Channel> boundAddresses = new 
ConcurrentHashMap<>();
-    protected final IoHandler handler;
 
     public NettyIoAcceptor(NettyIoServiceFactory factory, IoHandler handler) {
-        this.factory = factory;
-        this.handler = handler;
+        super(factory, handler);
+
         channelGroup = new DefaultChannelGroup("sshd-acceptor-channels", 
GlobalEventExecutor.INSTANCE);
         bootstrap.group(factory.eventLoopGroup)
             .channel(NioServerSocketChannel.class)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java
----------------------------------------------------------------------
diff --git 
a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java 
b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java
index 9dde3d9..e6f0065 100644
--- a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java
+++ b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java
@@ -48,11 +48,9 @@ import io.netty.util.concurrent.GlobalEventExecutor;
 public class NettyIoConnector extends NettyIoService implements IoConnector {
 
     protected final Bootstrap bootstrap = new Bootstrap();
-    protected final IoHandler handler;
 
     public NettyIoConnector(NettyIoServiceFactory factory, IoHandler handler) {
-        this.factory = factory;
-        this.handler = handler;
+        super(factory, handler);
         channelGroup = new DefaultChannelGroup("sshd-connector-channels", 
GlobalEventExecutor.INSTANCE);
         bootstrap.group(factory.eventLoopGroup)
             .channel(NioSocketChannel.class)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoService.java
----------------------------------------------------------------------
diff --git a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoService.java 
b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoService.java
index 9bd3ca3..a62326f 100644
--- a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoService.java
+++ b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoService.java
@@ -20,11 +20,14 @@
 package org.apache.sshd.netty;
 
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.sshd.common.io.IoConnectFuture;
+import org.apache.sshd.common.io.IoHandler;
 import org.apache.sshd.common.io.IoService;
+import org.apache.sshd.common.io.IoServiceEventListener;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.util.closeable.AbstractCloseable;
 
@@ -35,17 +38,32 @@ import io.netty.util.AttributeKey;
  * @author <a href="mailto:[email protected]";>Julien Viet</a>
  * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
-public class NettyIoService extends AbstractCloseable implements IoService {
+public abstract class NettyIoService extends AbstractCloseable implements 
IoService {
 
     public static final AttributeKey<IoConnectFuture> CONNECT_FUTURE_KEY = 
AttributeKey.valueOf(IoConnectFuture.class.getName());
 
     protected final AtomicLong sessionSeq = new AtomicLong();
     protected final Map<Long, IoSession> sessions = new ConcurrentHashMap<>();
-    protected NettyIoServiceFactory factory;
     protected ChannelGroup channelGroup;
+    protected final NettyIoServiceFactory factory;
+    protected final IoHandler handler;
 
-    public NettyIoService() {
-        super();
+    private IoServiceEventListener eventListener;
+
+    protected NettyIoService(NettyIoServiceFactory factory, IoHandler handler) 
{
+        this.factory = Objects.requireNonNull(factory, "No factory instance 
provided");
+        this.handler = Objects.requireNonNull(handler, "No I/O handler 
provied");
+        this.eventListener = factory.getIoServiceEventListener();
+    }
+
+    @Override
+    public IoServiceEventListener getIoServiceEventListener() {
+        return eventListener;
+    }
+
+    @Override
+    public void setIoServiceEventListener(IoServiceEventListener listener) {
+        eventListener = listener;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactory.java 
b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactory.java
index f65989b..aeeb07c 100644
--- a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactory.java
+++ b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactory.java
@@ -23,6 +23,7 @@ import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoConnector;
 import org.apache.sshd.common.io.IoHandler;
+import org.apache.sshd.common.io.IoServiceEventListener;
 import org.apache.sshd.common.io.IoServiceFactory;
 import org.apache.sshd.common.util.closeable.AbstractCloseable;
 
@@ -39,6 +40,8 @@ public class NettyIoServiceFactory extends AbstractCloseable 
implements IoServic
     protected final EventLoopGroup eventLoopGroup;
     protected final boolean closeEventLoopGroup;
 
+    private IoServiceEventListener eventListener;
+
     public NettyIoServiceFactory() {
         this(null);
     }
@@ -49,6 +52,16 @@ public class NettyIoServiceFactory extends AbstractCloseable 
implements IoServic
     }
 
     @Override
+    public IoServiceEventListener getIoServiceEventListener() {
+        return eventListener;
+    }
+
+    @Override
+    public void setIoServiceEventListener(IoServiceEventListener listener) {
+        eventListener = listener;
+    }
+
+    @Override
     public IoConnector createConnector(IoHandler handler) {
         return new NettyIoConnector(this, handler);
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/909e7ac0/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactoryFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactoryFactory.java
 
b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactoryFactory.java
index 8cafba2..54a0fa0 100644
--- 
a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactoryFactory.java
+++ 
b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoServiceFactoryFactory.java
@@ -19,6 +19,8 @@
 
 package org.apache.sshd.netty;
 
+import java.util.Objects;
+
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.io.AbstractIoServiceFactoryFactory;
 import org.apache.sshd.common.io.IoServiceFactory;
@@ -44,6 +46,9 @@ public class NettyIoServiceFactoryFactory extends 
AbstractIoServiceFactoryFactor
 
     @Override
     public IoServiceFactory create(FactoryManager manager) {
-        return new NettyIoServiceFactory(eventLoopGroup);
+        Objects.requireNonNull(manager, "No factory manager provided");
+        IoServiceFactory factory = new NettyIoServiceFactory(eventLoopGroup);
+        factory.setIoServiceEventListener(manager.getIoServiceEventListener());
+        return factory;
     }
 }

Reply via email to