Cleanup RpcRoutingStrategy definition
[controller.git] / opendaylight / netconf / netconf-netty-util / src / main / java / org / opendaylight / controller / netconf / nettyutil / handler / ssh / client / AsyncSshHanderReader.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.controller.netconf.nettyutil.handler.ssh.client;
10
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;
20
21 /**
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.
24  */
25 final class AsyncSshHanderReader implements SshFutureListener<IoReadFuture>, AutoCloseable {
26
27     private static final Logger logger = LoggerFactory.getLogger(AsyncSshHandler.class);
28
29     private static final int BUFFER_SIZE = 8192;
30
31     private final ChannelOutboundHandler asyncSshHandler;
32     private final ChannelHandlerContext ctx;
33
34     private IoInputStream asyncOut;
35     private Buffer buf;
36     private IoReadFuture currentReadFuture;
37
38     public AsyncSshHanderReader(final ChannelOutboundHandler asyncSshHandler, final ChannelHandlerContext ctx, final IoInputStream asyncOut) {
39         this.asyncSshHandler = asyncSshHandler;
40         this.ctx = ctx;
41         this.asyncOut = asyncOut;
42         buf = new Buffer(BUFFER_SIZE);
43         asyncOut.read(buf).addListener(this);
44     }
45
46     @Override
47     public synchronized void operationComplete(final IoReadFuture future) {
48         if(future.getException() != null) {
49             if(asyncOut.isClosed() || asyncOut.isClosing()) {
50                 // Ssh dropped
51                 logger.debug("Ssh session dropped on channel: {}", ctx.channel(), future.getException());
52             } else {
53                 logger.warn("Exception while reading from SSH remote on channel {}", ctx.channel(), future.getException());
54             }
55             invokeDisconnect();
56             return;
57         }
58
59         if (future.getRead() > 0) {
60             ctx.fireChannelRead(Unpooled.wrappedBuffer(buf.array(), 0, future.getRead()));
61
62             // Schedule next read
63             buf = new Buffer(BUFFER_SIZE);
64             currentReadFuture = asyncOut.read(buf);
65             currentReadFuture.addListener(this);
66         }
67     }
68
69     private void invokeDisconnect() {
70         try {
71             asyncSshHandler.disconnect(ctx, ctx.newPromise());
72         } catch (final Exception e) {
73             // This should not happen
74             throw new IllegalStateException(e);
75         }
76     }
77
78     @Override
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);
83         }
84
85         asyncOut = null;
86     }
87 }