package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
*/
public class AsyncSshHandler extends ChannelOutboundHandlerAdapter {
- private static final Logger logger = LoggerFactory.getLogger(AsyncSshHandler.class);
+ private static final Logger LOG = LoggerFactory.getLogger(AsyncSshHandler.class);
public static final String SUBSYSTEM = "netconf";
public static final SshClient DEFAULT_CLIENT = SshClient.setUpDefaultClient();
private final AuthenticationHandler authenticationHandler;
private final SshClient sshClient;
- private AsyncSshHanderReader sshReadAsyncListener;
+ private AsyncSshHandlerReader sshReadAsyncListener;
private AsyncSshHandlerWriter sshWriteAsyncHandler;
private ClientChannel channel;
}
private void startSsh(final ChannelHandlerContext ctx, final SocketAddress address) {
- logger.debug("Starting SSH to {} on channel: {}", address, ctx.channel());
+ LOG.debug("Starting SSH to {} on channel: {}", address, ctx.channel());
final ConnectFuture sshConnectionFuture = sshClient.connect(authenticationHandler.getUsername(), address);
sshConnectionFuture.addListener(new SshFutureListener<ConnectFuture>() {
private synchronized void handleSshSessionCreated(final ConnectFuture future, final ChannelHandlerContext ctx) {
try {
- logger.trace("SSH session created on channel: {}", ctx.channel());
+ LOG.trace("SSH session created on channel: {}", ctx.channel());
session = future.getSession();
final AuthFuture authenticateFuture = authenticationHandler.authenticate(session);
private synchronized void handleSshAuthenticated(final ClientSession session, final ChannelHandlerContext ctx) {
try {
- logger.debug("SSH session authenticated on channel: {}, server version: {}", ctx.channel(), session.getServerVersion());
+ LOG.debug("SSH session authenticated on channel: {}, server version: {}", ctx.channel(), session.getServerVersion());
channel = session.createSubsystemChannel(SUBSYSTEM);
channel.setStreaming(ClientChannel.Streaming.Async);
}
private synchronized void handleSshChanelOpened(final ChannelHandlerContext ctx) {
- logger.trace("SSH subsystem channel opened successfully on channel: {}", ctx.channel());
+ LOG.trace("SSH subsystem channel opened successfully on channel: {}", ctx.channel());
connectPromise.setSuccess();
connectPromise = null;
- sshReadAsyncListener = new AsyncSshHanderReader(this, ctx, channel.getAsyncOut());
+ // TODO we should also read from error stream and at least log from that
+
+ sshReadAsyncListener = new AsyncSshHandlerReader(new AutoCloseable() {
+ @Override
+ public void close() throws Exception {
+ AsyncSshHandler.this.disconnect(ctx, ctx.newPromise());
+ }
+ }, new AsyncSshHandlerReader.ReadMsgHandler() {
+ @Override
+ public void onMessageRead(final ByteBuf msg) {
+ ctx.fireChannelRead(msg);
+ }
+ }, channel.toString(), channel.getAsyncOut());
+
// if readAsyncListener receives immediate close, it will close this handler and closing this handler sets channel variable to null
if(channel != null) {
sshWriteAsyncHandler = new AsyncSshHandlerWriter(channel.getAsyncIn());
}
private synchronized void handleSshSetupFailure(final ChannelHandlerContext ctx, final Throwable e) {
- logger.warn("Unable to setup SSH connection on channel: {}", ctx.channel(), e);
+ LOG.warn("Unable to setup SSH connection on channel: {}", ctx.channel(), e);
connectPromise.setFailure(e);
connectPromise = null;
throw new IllegalStateException("Unable to setup SSH connection on channel: " + ctx.channel(), e);
channel = null;
promise.setSuccess();
- logger.debug("SSH session closed on channel: {}", ctx.channel());
+ LOG.debug("SSH session closed on channel: {}", ctx.channel());
ctx.fireChannelInactive();
}