Add workaround for SSH connection issue related to SSHD-1028
[netconf.git] / netconf / netconf-netty-util / src / main / java / org / opendaylight / netconf / nettyutil / handler / ssh / sshd1028 / NetconfNio2ServiceFactory.java
1 /*
2  * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netconf.nettyutil.handler.ssh.sshd1028;
9
10 import java.lang.reflect.Field;
11 import java.nio.channels.AsynchronousChannelGroup;
12 import java.security.AccessController;
13 import java.security.PrivilegedAction;
14 import org.opendaylight.netconf.shaded.sshd.common.FactoryManager;
15 import org.opendaylight.netconf.shaded.sshd.common.io.IoConnector;
16 import org.opendaylight.netconf.shaded.sshd.common.io.IoHandler;
17 import org.opendaylight.netconf.shaded.sshd.common.io.nio2.Nio2ServiceFactory;
18 import org.opendaylight.netconf.shaded.sshd.common.util.threads.CloseableExecutorService;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 /**
23  * Custom Nio2ServiceFactory which creates instances of NetconfNio2Connector instead of Nio2Connector.
24  * Should be removed when SSHD-1028 is fixed.
25  */
26 public class NetconfNio2ServiceFactory extends Nio2ServiceFactory {
27     private static final Logger LOG = LoggerFactory.getLogger(NetconfNio2ServiceFactory.class);
28     private static final Field FIELD_GROUP;
29
30     static {
31         final Field fieldGroup;
32         try {
33             fieldGroup = NetconfNio2ServiceFactory.class.getSuperclass().getDeclaredField("group");
34         } catch (NoSuchFieldException e) {
35             LOG.error("Cannot access the ChannelGroup from the " + "Nio2ServiceFactory");
36             throw new ExceptionInInitializerError(e);
37         }
38
39         AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
40             fieldGroup.setAccessible(true);
41             return null;
42         });
43
44         FIELD_GROUP = fieldGroup;
45     }
46
47     public NetconfNio2ServiceFactory(final FactoryManager factoryManager, final CloseableExecutorService service) {
48         super(factoryManager, service);
49     }
50
51     @Override
52     public IoConnector createConnector(final IoHandler handler) {
53         if (FIELD_GROUP != null) {
54             try {
55                 final AsynchronousChannelGroup group = (AsynchronousChannelGroup)FIELD_GROUP.get(this);
56                 return autowireCreatedService(new NetconfNio2Connector(getFactoryManager(), handler, group));
57             } catch (IllegalAccessException e) {
58                 LOG.error("NetconfNio2Connector cannot be instanciated. Creating default Nio2Connector instead.");
59             }
60         }
61
62         return super.createConnector(handler);
63     }
64 }