Deprecate legacy SSH integration
[netconf.git] / netconf / callhome-protocol / src / main / java / org / opendaylight / netconf / callhome / protocol / MinaSshNettyChannel.java
1 /*
2  * Copyright (c) 2016 Brocade Communication Systems 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.callhome.protocol;
9
10 import static java.util.Objects.requireNonNull;
11
12 import io.netty.channel.AbstractServerChannel;
13 import io.netty.channel.ChannelConfig;
14 import io.netty.channel.ChannelMetadata;
15 import io.netty.channel.ChannelOutboundBuffer;
16 import io.netty.channel.ChannelPromise;
17 import io.netty.channel.DefaultChannelConfig;
18 import io.netty.channel.EventLoop;
19 import java.net.SocketAddress;
20 import org.opendaylight.netconf.callhome.protocol.CallHomeSessionContext.SshWriteAsyncHandlerAdapter;
21 import org.opendaylight.netconf.shaded.sshd.client.session.ClientSession;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 @Deprecated(since = "7.0.0", forRemoval = true)
26 // Non-final for testing
27 class MinaSshNettyChannel extends AbstractServerChannel {
28     private static final Logger LOG = LoggerFactory.getLogger(MinaSshNettyChannel.class);
29     private static final ChannelMetadata METADATA = new ChannelMetadata(false);
30
31     private final ChannelConfig config = new DefaultChannelConfig(this);
32     private final CallHomeSessionContext context;
33     private final ClientSession session;
34
35     private volatile boolean nettyClosed = false;
36
37     MinaSshNettyChannel(final CallHomeSessionContext context, final ClientSession session) {
38         this.context = requireNonNull(context);
39         this.session = requireNonNull(session);
40     }
41
42     @Override
43     public ChannelConfig config() {
44         return config;
45     }
46
47     private static boolean notClosing(final org.opendaylight.netconf.shaded.sshd.common.Closeable sshCloseable) {
48         return !sshCloseable.isClosing() && !sshCloseable.isClosed();
49     }
50
51     @Override
52     public boolean isOpen() {
53         return notClosing(session);
54     }
55
56     @Override
57     public boolean isActive() {
58         return notClosing(session);
59     }
60
61     @Override
62     public ChannelMetadata metadata() {
63         return METADATA;
64     }
65
66     @Override
67     protected AbstractUnsafe newUnsafe() {
68         return new SshUnsafe();
69     }
70
71     @Override
72     protected boolean isCompatible(final EventLoop loop) {
73         return true;
74     }
75
76     @Override
77     protected SocketAddress localAddress0() {
78         return session.getIoSession().getLocalAddress();
79     }
80
81     @Override
82     protected SocketAddress remoteAddress0() {
83         return context.getRemoteAddress();
84     }
85
86     @Override
87     protected void doBind(final SocketAddress localAddress) {
88         throw new UnsupportedOperationException("Bind not supported.");
89     }
90
91     void doMinaDisconnect(final boolean blocking) {
92         if (notClosing(session)) {
93             session.close(blocking);
94             if (pipeline().first() instanceof SshWriteAsyncHandlerAdapter asyncHandlerAdapter) {
95                 asyncHandlerAdapter.getSshChannel().close(blocking);
96             }
97         }
98     }
99
100     void doNettyDisconnect() {
101         if (!nettyClosed) {
102             nettyClosed = true;
103             pipeline().fireChannelInactive();
104         }
105     }
106
107     @Override
108     protected void doDisconnect() {
109         LOG.info("Disconnect invoked");
110         doNettyDisconnect();
111         doMinaDisconnect(false);
112     }
113
114     @Override
115     protected void doClose() {
116         context.removeSelf();
117         if (notClosing(session)) {
118             session.close(true);
119             if (pipeline().first() instanceof SshWriteAsyncHandlerAdapter asyncHandlerAdapter) {
120                 asyncHandlerAdapter.getSshChannel().close(true);
121             }
122         }
123     }
124
125     @Override
126     protected void doBeginRead() {
127         // Intentional NOOP
128     }
129
130     @Override
131     protected void doWrite(final ChannelOutboundBuffer in) {
132         throw new IllegalStateException("Outbound writes to SSH should be done by SSH Write handler");
133     }
134
135     private final class SshUnsafe extends AbstractUnsafe {
136         @Override
137         public void connect(final SocketAddress remoteAddress, final SocketAddress localAddress,
138                 final ChannelPromise promise) {
139             throw new UnsupportedOperationException("Unsafe is not supported.");
140         }
141     }
142 }