diff src/ch/ethz/ssh2/channel/Channel.java @ 308:42b15aaa7ac7 ganymed

merge
author Carl Byington <carl@five-ten-sg.com>
date Wed, 30 Jul 2014 14:21:50 -0700
parents 071eccdff8ea
children
line wrap: on
line diff
--- a/src/ch/ethz/ssh2/channel/Channel.java	Wed Jul 30 13:38:04 2014 -0700
+++ b/src/ch/ethz/ssh2/channel/Channel.java	Wed Jul 30 14:21:50 2014 -0700
@@ -14,208 +14,192 @@
  * @author Christian Plattner
  * @version $Id: Channel.java 123 2014-04-12 21:11:47Z dkocher@sudo.ch $
  */
-public class Channel
-{
-	/*
-		  * OK. Here is an important part of the JVM Specification:
-		  * (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html#22214)
-		  *
-		  * Any association between locks and variables is purely conventional.
-		  * Locking any lock conceptually flushes all variables from a thread's
-		  * working memory, and unlocking any lock forces the writing out to main
-		  * memory of all variables that the thread has assigned. That a lock may be
-		  * associated with a particular object or a class is purely a convention.
-		  * (...)
-		  *
-		  * If a thread uses a particular shared variable only after locking a
-		  * particular lock and before the corresponding unlocking of that same lock,
-		  * then the thread will read the shared value of that variable from main
-		  * memory after the lock operation, if necessary, and will copy back to main
-		  * memory the value most recently assigned to that variable before the
-		  * unlock operation.
-		  *
-		  * This, in conjunction with the mutual exclusion rules for locks, suffices
-		  * to guarantee that values are correctly transmitted from one thread to
-		  * another through shared variables.
-		  *
-		  * ====> Always keep that in mind when modifying the Channel/ChannelManger
-		  * code.
-		  *
-		  */
+public class Channel {
+    /*
+          * OK. Here is an important part of the JVM Specification:
+          * (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html#22214)
+          *
+          * Any association between locks and variables is purely conventional.
+          * Locking any lock conceptually flushes all variables from a thread's
+          * working memory, and unlocking any lock forces the writing out to main
+          * memory of all variables that the thread has assigned. That a lock may be
+          * associated with a particular object or a class is purely a convention.
+          * (...)
+          *
+          * If a thread uses a particular shared variable only after locking a
+          * particular lock and before the corresponding unlocking of that same lock,
+          * then the thread will read the shared value of that variable from main
+          * memory after the lock operation, if necessary, and will copy back to main
+          * memory the value most recently assigned to that variable before the
+          * unlock operation.
+          *
+          * This, in conjunction with the mutual exclusion rules for locks, suffices
+          * to guarantee that values are correctly transmitted from one thread to
+          * another through shared variables.
+          *
+          * ====> Always keep that in mind when modifying the Channel/ChannelManger
+          * code.
+          *
+          */
 
-	public static final int STATE_OPENING = 1;
-	public static final int STATE_OPEN = 2;
-	public static final int STATE_CLOSED = 4;
+    public static final int STATE_OPENING = 1;
+    public static final int STATE_OPEN = 2;
+    public static final int STATE_CLOSED = 4;
 
-	static final int CHANNEL_BUFFER_SIZE = 32 * 1024 * 3 * 2;
+    static final int CHANNEL_BUFFER_SIZE = 32 * 1024 * 3 * 2;
 
-	/*
-		  * To achieve correctness, the following rules have to be respected when
-		  * accessing this object:
-		  */
+    /*
+          * To achieve correctness, the following rules have to be respected when
+          * accessing this object:
+          */
 
-	// These fields can always be read
-	final ChannelManager cm;
-	final ChannelOutputStream stdinStream;
-	final ChannelInputStream stdoutStream;
-	final ChannelInputStream stderrStream;
-
-	// In case this channel belongs to a server-side session.
-	ServerSessionImpl ss;
+    // These fields can always be read
+    final ChannelManager cm;
+    final ChannelOutputStream stdinStream;
+    final ChannelInputStream stdoutStream;
+    final ChannelInputStream stderrStream;
 
-	// These two fields will only be written while the Channel is in state
-	// STATE_OPENING.
-	// The code makes sure that the two fields are written out when the state is
-	// changing to STATE_OPEN.
-	// Therefore, if you know that the Channel is in state STATE_OPEN, then you
-	// can read these two fields without synchronizing on the Channel. However, make
-	// sure that you get the latest values (e.g., flush caches by synchronizing on any
-	// object). However, to be on the safe side, you can lock the channel.
-
-	int localID = -1;
-	int remoteID = -1;
+    // In case this channel belongs to a server-side session.
+    ServerSessionImpl ss;
 
-	/*
-		  * Make sure that we never send a data/EOF/WindowChange msg after a CLOSE
-		  * msg.
-		  *
-		  * This is a little bit complicated, but we have to do it in that way, since
-		  * we cannot keep a lock on the Channel during the send operation (this
-		  * would block sometimes the receiver thread, and, in extreme cases, can
-		  * lead to a deadlock on both sides of the connection (senders are blocked
-		  * since the receive buffers on the other side are full, and receiver
-		  * threads wait for the senders to finish). It all depends on the
-		  * implementation on the other side. But we cannot make any assumptions, we
-		  * have to assume the worst case. Confused? Just believe me.
-		  */
+    // These two fields will only be written while the Channel is in state
+    // STATE_OPENING.
+    // The code makes sure that the two fields are written out when the state is
+    // changing to STATE_OPEN.
+    // Therefore, if you know that the Channel is in state STATE_OPEN, then you
+    // can read these two fields without synchronizing on the Channel. However, make
+    // sure that you get the latest values (e.g., flush caches by synchronizing on any
+    // object). However, to be on the safe side, you can lock the channel.
+
+    int localID = -1;
+    int remoteID = -1;
 
-	/*
-		  * If you send a message on a channel, then you have to aquire the
-		  * "channelSendLock" and check the "closeMessageSent" flag (this variable
-		  * may only be accessed while holding the "channelSendLock" !!!
-		  *
-		  * BTW: NEVER EVER SEND MESSAGES FROM THE RECEIVE THREAD - see explanation
-		  * above.
-		  */
-
-	final Object channelSendLock = new Object();
-	boolean closeMessageSent = false;
+    /*
+          * Make sure that we never send a data/EOF/WindowChange msg after a CLOSE
+          * msg.
+          *
+          * This is a little bit complicated, but we have to do it in that way, since
+          * we cannot keep a lock on the Channel during the send operation (this
+          * would block sometimes the receiver thread, and, in extreme cases, can
+          * lead to a deadlock on both sides of the connection (senders are blocked
+          * since the receive buffers on the other side are full, and receiver
+          * threads wait for the senders to finish). It all depends on the
+          * implementation on the other side. But we cannot make any assumptions, we
+          * have to assume the worst case. Confused? Just believe me.
+          */
 
-	/*
-		  * Stop memory fragmentation by allocating this often used buffer.
-		  * May only be used while holding the channelSendLock
-		  */
-
-	final byte[] msgWindowAdjust = new byte[9];
+    /*
+          * If you send a message on a channel, then you have to aquire the
+          * "channelSendLock" and check the "closeMessageSent" flag (this variable
+          * may only be accessed while holding the "channelSendLock" !!!
+          *
+          * BTW: NEVER EVER SEND MESSAGES FROM THE RECEIVE THREAD - see explanation
+          * above.
+          */
 
-	// If you access (read or write) any of the following fields, then you have
-	// to synchronize on the channel.
+    final Object channelSendLock = new Object();
+    boolean closeMessageSent = false;
 
-	int state = STATE_OPENING;
+    /*
+          * Stop memory fragmentation by allocating this often used buffer.
+          * May only be used while holding the channelSendLock
+          */
 
-	boolean closeMessageRecv = false;
+    final byte[] msgWindowAdjust = new byte[9];
 
-	/* This is a stupid implementation. At the moment we can only wait
-		  * for one pending request per channel.
-		  */
-	int successCounter = 0;
-	int failedCounter = 0;
+    // If you access (read or write) any of the following fields, then you have
+    // to synchronize on the channel.
 
-	int localWindow = 0; /* locally, we use a small window, < 2^31 */
-	long remoteWindow = 0; /* long for readable  2^32 - 1 window support */
+    int state = STATE_OPENING;
 
-	int localMaxPacketSize = -1;
-	int remoteMaxPacketSize = -1;
+    boolean closeMessageRecv = false;
 
-	final byte[] stdoutBuffer = new byte[CHANNEL_BUFFER_SIZE];
-	final byte[] stderrBuffer = new byte[CHANNEL_BUFFER_SIZE];
+    /* This is a stupid implementation. At the moment we can only wait
+          * for one pending request per channel.
+          */
+    int successCounter = 0;
+    int failedCounter = 0;
 
-	int stdoutReadpos = 0;
-	int stdoutWritepos = 0;
-	int stderrReadpos = 0;
-	int stderrWritepos = 0;
+    int localWindow = 0; /* locally, we use a small window, < 2^31 */
+    long remoteWindow = 0; /* long for readable  2^32 - 1 window support */
 
-	boolean EOF = false;
+    int localMaxPacketSize = -1;
+    int remoteMaxPacketSize = -1;
 
-	Integer exit_status;
-
-	String exit_signal;
+    final byte[] stdoutBuffer = new byte[CHANNEL_BUFFER_SIZE];
+    final byte[] stderrBuffer = new byte[CHANNEL_BUFFER_SIZE];
 
-	// we keep the x11 cookie so that this channel can be closed when this
-	// specific x11 forwarding gets stopped
-
-	String hexX11FakeCookie;
+    int stdoutReadpos = 0;
+    int stdoutWritepos = 0;
+    int stderrReadpos = 0;
+    int stderrWritepos = 0;
 
-	// reasonClosed is special, since we sometimes need to access it
-	// while holding the channelSendLock.
-	// We protect it with a private short term lock.
+    boolean EOF = false;
 
-	private final Object reasonClosedLock = new Object();
-	private IOException reasonClosed = null;
+    Integer exit_status;
+
+    String exit_signal;
 
-	public Channel(ChannelManager cm)
-	{
-		this.cm = cm;
+    // we keep the x11 cookie so that this channel can be closed when this
+    // specific x11 forwarding gets stopped
 
-		this.localWindow = CHANNEL_BUFFER_SIZE;
-        this.localMaxPacketSize = TransportManager.MAX_PACKET_SIZE;
+    String hexX11FakeCookie;
 
-		this.stdinStream = new ChannelOutputStream(this);
-		this.stdoutStream = new ChannelInputStream(this, false);
-		this.stderrStream = new ChannelInputStream(this, true);
-	}
+    // reasonClosed is special, since we sometimes need to access it
+    // while holding the channelSendLock.
+    // We protect it with a private short term lock.
 
-	/* Methods to allow access from classes outside of this package */
+    private final Object reasonClosedLock = new Object();
+    private IOException reasonClosed = null;
 
-	public ChannelInputStream getStderrStream()
-	{
-		return stderrStream;
-	}
+    public Channel(ChannelManager cm) {
+        this.cm = cm;
+        this.localWindow = CHANNEL_BUFFER_SIZE;
+        this.localMaxPacketSize = TransportManager.MAX_PACKET_SIZE;
+        this.stdinStream = new ChannelOutputStream(this);
+        this.stdoutStream = new ChannelInputStream(this, false);
+        this.stderrStream = new ChannelInputStream(this, true);
+    }
 
-	public ChannelOutputStream getStdinStream()
-	{
-		return stdinStream;
-	}
+    /* Methods to allow access from classes outside of this package */
 
-	public ChannelInputStream getStdoutStream()
-	{
-		return stdoutStream;
-	}
+    public ChannelInputStream getStderrStream() {
+        return stderrStream;
+    }
 
-	public String getExitSignal()
-	{
-		synchronized (this)
-		{
-			return exit_signal;
-		}
-	}
+    public ChannelOutputStream getStdinStream() {
+        return stdinStream;
+    }
+
+    public ChannelInputStream getStdoutStream() {
+        return stdoutStream;
+    }
 
-	public Integer getExitStatus()
-	{
-		synchronized (this)
-		{
-			return exit_status;
-		}
-	}
+    public String getExitSignal() {
+        synchronized (this) {
+            return exit_signal;
+        }
+    }
+
+    public Integer getExitStatus() {
+        synchronized (this) {
+            return exit_status;
+        }
+    }
 
-	public IOException getReasonClosed()
-	{
-		synchronized (reasonClosedLock)
-		{
-			return reasonClosed;
-		}
-	}
+    public IOException getReasonClosed() {
+        synchronized (reasonClosedLock) {
+            return reasonClosed;
+        }
+    }
 
-	public void setReasonClosed(IOException e)
-	{
-		synchronized (reasonClosedLock)
-		{
+    public void setReasonClosed(IOException e) {
+        synchronized (reasonClosedLock) {
             this.reasonClosed = e;
-		}
-	}
+        }
+    }
 
-	public int getState()
-	{
-		return this.state;
-	}
+    public int getState() {
+        return this.state;
+    }
 }