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.nettyutil.handler.ssh.client;
11 import io.netty.buffer.Unpooled;
12 import io.netty.channel.ChannelHandlerContext;
13 import io.netty.channel.ChannelOutboundHandler;
14 import org.apache.sshd.common.future.SshFutureListener;
15 import org.apache.sshd.common.io.IoInputStream;
16 import org.apache.sshd.common.io.IoReadFuture;
17 import org.apache.sshd.common.util.Buffer;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
22 * Listener on async input stream from SSH session.
23 * This listeners schedules reads in a loop until the session is closed or read fails.
25 final class AsyncSshHanderReader implements SshFutureListener<IoReadFuture>, AutoCloseable {
27 private static final Logger logger = LoggerFactory.getLogger(AsyncSshHandler.class);
29 private static final int BUFFER_SIZE = 8192;
31 private final ChannelOutboundHandler asyncSshHandler;
32 private final ChannelHandlerContext ctx;
34 private IoInputStream asyncOut;
36 private IoReadFuture currentReadFuture;
38 public AsyncSshHanderReader(final ChannelOutboundHandler asyncSshHandler, final ChannelHandlerContext ctx, final IoInputStream asyncOut) {
39 this.asyncSshHandler = asyncSshHandler;
41 this.asyncOut = asyncOut;
42 buf = new Buffer(BUFFER_SIZE);
43 asyncOut.read(buf).addListener(this);
47 public synchronized void operationComplete(final IoReadFuture future) {
48 if(future.getException() != null) {
49 if(asyncOut.isClosed() || asyncOut.isClosing()) {
51 logger.debug("Ssh session dropped on channel: {}", ctx.channel(), future.getException());
53 logger.warn("Exception while reading from SSH remote on channel {}", ctx.channel(), future.getException());
59 if (future.getRead() > 0) {
60 ctx.fireChannelRead(Unpooled.wrappedBuffer(buf.array(), 0, future.getRead()));
63 buf = new Buffer(BUFFER_SIZE);
64 currentReadFuture = asyncOut.read(buf);
65 currentReadFuture.addListener(this);
69 private void invokeDisconnect() {
71 asyncSshHandler.disconnect(ctx, ctx.newPromise());
72 } catch (final Exception e) {
73 // This should not happen
74 throw new IllegalStateException(e);
79 public synchronized void close() {
80 // Remove self as listener on close to prevent reading from closed input
81 if(currentReadFuture != null) {
82 currentReadFuture.removeListener(this);