org.opendaylight.netconf.ssh.SshProxyClientHandler Maven / Gradle / Ivy
/*
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.netconf.ssh;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.nio.charset.StandardCharsets;
import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.netconf.nettyutil.handler.ssh.client.AsyncSshHandlerReader;
import org.opendaylight.netconf.nettyutil.handler.ssh.client.AsyncSshHandlerWriter;
import org.opendaylight.netconf.shaded.sshd.common.io.IoInputStream;
import org.opendaylight.netconf.shaded.sshd.common.io.IoOutputStream;
import org.opendaylight.netconf.shaded.sshd.server.ExitCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Netty handler that reads SSH from remote client and writes to delegate server
* and reads from delegate server and writes to remote client.
*/
final class SshProxyClientHandler extends ChannelInboundHandlerAdapter {
private static final Logger LOG = LoggerFactory.getLogger(SshProxyClientHandler.class);
private final IoInputStream in;
private final IoOutputStream out;
private AsyncSshHandlerReader asyncSshHandlerReader;
private AsyncSshHandlerWriter asyncSshHandlerWriter;
private final NetconfHelloMessageAdditionalHeader netconfHelloMessageAdditionalHeader;
private final ExitCallback callback;
SshProxyClientHandler(final IoInputStream in, final IoOutputStream out,
final NetconfHelloMessageAdditionalHeader netconfHelloMessageAdditionalHeader,
final ExitCallback callback) {
this.in = in;
this.out = out;
this.netconfHelloMessageAdditionalHeader = netconfHelloMessageAdditionalHeader;
this.callback = callback;
}
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
writeAdditionalHeader(ctx);
asyncSshHandlerWriter = new AsyncSshHandlerWriter(out);
asyncSshHandlerReader = new AsyncSshHandlerReader(() -> {
// Close both sessions (delegate server and remote client)
ctx.fireChannelInactive();
ctx.disconnect();
ctx.close();
asyncSshHandlerReader.close();
asyncSshHandlerWriter.close();
}, msg -> {
if (LOG.isTraceEnabled()) {
LOG.trace("Forwarding message for client: {} on channel: {}, message: {}",
netconfHelloMessageAdditionalHeader.getAddress(), ctx.channel(),
AsyncSshHandlerWriter.byteBufToString(msg));
}
// Just forward to delegate
ctx.writeAndFlush(msg);
}, "ssh" + netconfHelloMessageAdditionalHeader.getAddress(), in);
super.channelActive(ctx);
}
private void writeAdditionalHeader(final ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.copiedBuffer(netconfHelloMessageAdditionalHeader.toFormattedString()
.getBytes(StandardCharsets.UTF_8)));
}
@Override
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
asyncSshHandlerWriter.write(ctx, msg, ctx.newPromise());
}
@Override
public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
LOG.debug("Internal connection to netconf server was dropped for client: {} on channel: {}",
netconfHelloMessageAdditionalHeader.getAddress(), ctx.channel());
callback.onExit(1, "Internal connection to netconf server was dropped for client: "
+ netconfHelloMessageAdditionalHeader.getAddress() + " on channel: " + ctx.channel());
super.channelInactive(ctx);
}
}