2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.netconf.ssh;
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.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandlerReader;
19 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandlerWriter;
20 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * Netty handler that reads SSH from remote client and writes to delegate server and reads from delegate server and writes to remote client
27 final class SshProxyClientHandler extends ChannelInboundHandlerAdapter {
29 private static final Logger logger = LoggerFactory.getLogger(SshProxyClientHandler.class);
31 private final IoInputStream in;
32 private final IoOutputStream out;
34 private AsyncSshHandlerReader asyncSshHandlerReader;
35 private AsyncSshHandlerWriter asyncSshHandlerWriter;
37 private final NetconfHelloMessageAdditionalHeader netconfHelloMessageAdditionalHeader;
38 private final ExitCallback callback;
40 public SshProxyClientHandler(final IoInputStream in, final IoOutputStream out,
41 final NetconfHelloMessageAdditionalHeader netconfHelloMessageAdditionalHeader,
42 final ExitCallback callback) {
45 this.netconfHelloMessageAdditionalHeader = netconfHelloMessageAdditionalHeader;
46 this.callback = callback;
50 public void channelActive(final ChannelHandlerContext ctx) throws Exception {
51 writeAdditionalHeader(ctx);
53 asyncSshHandlerWriter = new AsyncSshHandlerWriter(out);
54 asyncSshHandlerReader = new AsyncSshHandlerReader(new AutoCloseable() {
56 public void close() throws Exception {
57 // Close both sessions (delegate server and remote client)
58 ctx.fireChannelInactive();
61 asyncSshHandlerReader.close();
62 asyncSshHandlerWriter.close();
64 }, new AsyncSshHandlerReader.ReadMsgHandler() {
66 public void onMessageRead(final ByteBuf msg) {
67 if(logger.isTraceEnabled()) {
68 logger.trace("Forwarding message for client: {} on channel: {}, message: {}",
69 netconfHelloMessageAdditionalHeader.getAddress(), ctx.channel(), AsyncSshHandlerWriter.byteBufToString(msg));
71 // Just forward to delegate
72 ctx.writeAndFlush(msg);
74 }, "ssh" + netconfHelloMessageAdditionalHeader.getAddress(), in);
77 super.channelActive(ctx);
80 private void writeAdditionalHeader(final ChannelHandlerContext ctx) {
81 ctx.writeAndFlush(Unpooled.copiedBuffer(netconfHelloMessageAdditionalHeader.toFormattedString().getBytes()));
85 public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
86 asyncSshHandlerWriter.write(ctx, msg, ctx.newPromise());
90 public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
91 logger.debug("Internal connection to netconf server was dropped for client: {} on channel: ",
92 netconfHelloMessageAdditionalHeader.getAddress(), ctx.channel());
93 callback.onExit(1, "Internal connection to netconf server was dropped for client: " +
94 netconfHelloMessageAdditionalHeader.getAddress() + " on channel: " + ctx.channel());
95 super.channelInactive(ctx);