Add 'features/protocol-framework/' from commit 'cb42405784db97d0ce2c5991d12a89b46d185949'
[netconf.git] / netconf / netconf-ssh / src / main / java / org / opendaylight / netconf / ssh / SshProxyClientHandler.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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
9 package org.opendaylight.netconf.ssh;
10
11 import io.netty.buffer.ByteBuf;
12 import io.netty.buffer.Unpooled;
13 import io.netty.channel.ChannelHandlerContext;
14 import io.netty.channel.ChannelInboundHandlerAdapter;
15 import org.apache.sshd.common.io.IoInputStream;
16 import org.apache.sshd.common.io.IoOutputStream;
17 import org.apache.sshd.server.ExitCallback;
18 import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader;
19 import org.opendaylight.netconf.nettyutil.handler.ssh.client.AsyncSshHandlerReader;
20 import org.opendaylight.netconf.nettyutil.handler.ssh.client.AsyncSshHandlerWriter;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * Netty handler that reads SSH from remote client and writes to delegate server
26  * and reads from delegate server and writes to remote client.
27  */
28 final class SshProxyClientHandler extends ChannelInboundHandlerAdapter {
29
30     private static final Logger LOG = LoggerFactory.getLogger(SshProxyClientHandler.class);
31
32     private final IoInputStream in;
33     private final IoOutputStream out;
34
35     private AsyncSshHandlerReader asyncSshHandlerReader;
36     private AsyncSshHandlerWriter asyncSshHandlerWriter;
37
38     private final NetconfHelloMessageAdditionalHeader netconfHelloMessageAdditionalHeader;
39     private final ExitCallback callback;
40
41     SshProxyClientHandler(final IoInputStream in, final IoOutputStream out,
42                           final NetconfHelloMessageAdditionalHeader netconfHelloMessageAdditionalHeader,
43                           final ExitCallback callback) {
44         this.in = in;
45         this.out = out;
46         this.netconfHelloMessageAdditionalHeader = netconfHelloMessageAdditionalHeader;
47         this.callback = callback;
48     }
49
50     @Override
51     public void channelActive(final ChannelHandlerContext ctx) throws Exception {
52         writeAdditionalHeader(ctx);
53
54         asyncSshHandlerWriter = new AsyncSshHandlerWriter(out);
55         asyncSshHandlerReader = new AsyncSshHandlerReader(new AutoCloseable() {
56             @Override
57             public void close() throws Exception {
58                 // Close both sessions (delegate server and remote client)
59                 ctx.fireChannelInactive();
60                 ctx.disconnect();
61                 ctx.close();
62                 asyncSshHandlerReader.close();
63                 asyncSshHandlerWriter.close();
64             }
65         }, new AsyncSshHandlerReader.ReadMsgHandler() {
66             @Override
67             public void onMessageRead(final ByteBuf msg) {
68                 if (LOG.isTraceEnabled()) {
69                     LOG.trace("Forwarding message for client: {} on channel: {}, message: {}",
70                             netconfHelloMessageAdditionalHeader.getAddress(), ctx.channel(),
71                             AsyncSshHandlerWriter.byteBufToString(msg));
72                 }
73                 // Just forward to delegate
74                 ctx.writeAndFlush(msg);
75             }
76         }, "ssh" + netconfHelloMessageAdditionalHeader.getAddress(), in);
77
78
79         super.channelActive(ctx);
80     }
81
82     private void writeAdditionalHeader(final ChannelHandlerContext ctx) {
83         ctx.writeAndFlush(Unpooled.copiedBuffer(netconfHelloMessageAdditionalHeader.toFormattedString().getBytes()));
84     }
85
86     @Override
87     public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
88         asyncSshHandlerWriter.write(ctx, msg, ctx.newPromise());
89     }
90
91     @Override
92     public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
93         LOG.debug("Internal connection to netconf server was dropped for client: {} on channel: ",
94                 netconfHelloMessageAdditionalHeader.getAddress(), ctx.channel());
95         callback.onExit(1, "Internal connection to netconf server was dropped for client: "
96                 + netconfHelloMessageAdditionalHeader.getAddress() + " on channel: " + ctx.channel());
97         super.channelInactive(ctx);
98     }
99
100
101 }