148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/* 248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Please refer to the LICENSE.txt for licensing details. 448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpackage ch.ethz.ssh2.channel; 648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/** 848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Channel. 948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 1048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @author Christian Plattner 1148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @version $Id: Channel.java 14 2011-05-27 14:28:21Z dkocher@sudo.ch $ 1248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 1348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpublic class Channel 1448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood{ 1548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 1648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * OK. Here is an important part of the JVM Specification: 1748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html#22214) 1848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 1948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Any association between locks and variables is purely conventional. 2048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Locking any lock conceptually flushes all variables from a thread's 2148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * working memory, and unlocking any lock forces the writing out to main 2248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * memory of all variables that the thread has assigned. That a lock may be 2348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * associated with a particular object or a class is purely a convention. 2448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (...) 2548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 2648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If a thread uses a particular shared variable only after locking a 2748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * particular lock and before the corresponding unlocking of that same lock, 2848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * then the thread will read the shared value of that variable from main 2948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * memory after the lock operation, if necessary, and will copy back to main 3048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * memory the value most recently assigned to that variable before the 3148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * unlock operation. 3248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 3348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This, in conjunction with the mutual exclusion rules for locks, suffices 3448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * to guarantee that values are correctly transmitted from one thread to 3548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * another through shared variables. 3648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 3748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * ====> Always keep that in mind when modifying the Channel/ChannelManger 3848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * code. 3948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 4048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 4148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public static final int STATE_OPENING = 1; 4348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public static final int STATE_OPEN = 2; 4448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public static final int STATE_CLOSED = 4; 4548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood static final int CHANNEL_BUFFER_SIZE = 32 * 1024 * 3 * 2; 4748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 4948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * To achieve correctness, the following rules have to be respected when 5048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * accessing this object: 5148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 5248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // These fields can always be read 5448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final ChannelManager cm; 5548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final ChannelOutputStream stdinStream; 5648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final ChannelInputStream stdoutStream; 5748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final ChannelInputStream stderrStream; 5848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // These two fields will only be written while the Channel is in state 6048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // STATE_OPENING. 6148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // The code makes sure that the two fields are written out when the state is 6248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // changing to STATE_OPEN. 6348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // Therefore, if you know that the Channel is in state STATE_OPEN, then you 6448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // can read these two fields without synchronizing on the Channel. However, make 6548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // sure that you get the latest values (e.g., flush caches by synchronizing on any 6648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // object). However, to be on the safe side, you can lock the channel. 6748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int localID = -1; 6948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int remoteID = -1; 7048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 7148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 7248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Make sure that we never send a data/EOF/WindowChange msg after a CLOSE 7348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * msg. 7448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 7548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This is a little bit complicated, but we have to do it in that way, since 7648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * we cannot keep a lock on the Channel during the send operation (this 7748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * would block sometimes the receiver thread, and, in extreme cases, can 7848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * lead to a deadlock on both sides of the connection (senders are blocked 7948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * since the receive buffers on the other side are full, and receiver 8048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * threads wait for the senders to finish). It all depends on the 8148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * implementation on the other side. But we cannot make any assumptions, we 8248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * have to assume the worst case. Confused? Just believe me. 8348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 8448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 8548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 8648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If you send a message on a channel, then you have to aquire the 8748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * "channelSendLock" and check the "closeMessageSent" flag (this variable 8848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * may only be accessed while holding the "channelSendLock" !!! 8948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 9048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * BTW: NEVER EVER SEND MESSAGES FROM THE RECEIVE THREAD - see explanation 9148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * above. 9248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 9348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final Object channelSendLock = new Object(); 9548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean closeMessageSent = false; 9648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 9848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Stop memory fragmentation by allocating this often used buffer. 9948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * May only be used while holding the channelSendLock 10048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 10148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final byte[] msgWindowAdjust = new byte[9]; 10348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // If you access (read or write) any of the following fields, then you have 10548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // to synchronize on the channel. 10648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int state = STATE_OPENING; 10848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean closeMessageRecv = false; 11048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 11148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* This is a stupid implementation. At the moment we can only wait 11248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * for one pending request per channel. 11348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 11448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int successCounter = 0; 11548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int failedCounter = 0; 11648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 11748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int localWindow = 0; /* locally, we use a small window, < 2^31 */ 11848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood long remoteWindow = 0; /* long for readable 2^32 - 1 window support */ 11948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 12048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int localMaxPacketSize = -1; 12148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int remoteMaxPacketSize = -1; 12248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 12348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final byte[] stdoutBuffer = new byte[CHANNEL_BUFFER_SIZE]; 12448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final byte[] stderrBuffer = new byte[CHANNEL_BUFFER_SIZE]; 12548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 12648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int stdoutReadpos = 0; 12748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int stdoutWritepos = 0; 12848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int stderrReadpos = 0; 12948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int stderrWritepos = 0; 13048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean EOF = false; 13248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood Integer exit_status; 13448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String exit_signal; 13648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // we keep the x11 cookie so that this channel can be closed when this 13848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // specific x11 forwarding gets stopped 13948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String hexX11FakeCookie; 14148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // reasonClosed is special, since we sometimes need to access it 14348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // while holding the channelSendLock. 14448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // We protect it with a private short term lock. 14548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private final Object reasonClosedLock = new Object(); 14748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private String reasonClosed = null; 14848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public Channel(ChannelManager cm) 15048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 15148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.cm = cm; 15248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 15348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.localWindow = CHANNEL_BUFFER_SIZE; 15448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.localMaxPacketSize = 32 * 1024; 15548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 15648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.stdinStream = new ChannelOutputStream(this); 15748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.stdoutStream = new ChannelInputStream(this, false); 15848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.stderrStream = new ChannelInputStream(this, true); 15948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 16048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 16148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Methods to allow access from classes outside of this package */ 16248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 16348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public ChannelInputStream getStderrStream() 16448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 16548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return stderrStream; 16648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 16748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 16848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public ChannelOutputStream getStdinStream() 16948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 17048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return stdinStream; 17148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 17248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 17348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public ChannelInputStream getStdoutStream() 17448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 17548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return stdoutStream; 17648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 17748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 17848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public String getExitSignal() 17948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 18048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood synchronized (this) 18148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 18248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return exit_signal; 18348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 18448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 18548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 18648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public Integer getExitStatus() 18748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 18848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood synchronized (this) 18948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 19048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return exit_status; 19148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 19248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 19348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 19448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public String getReasonClosed() 19548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 19648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood synchronized (reasonClosedLock) 19748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 19848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return reasonClosed; 19948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 20048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 20148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 20248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void setReasonClosed(String reasonClosed) 20348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 20448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood synchronized (reasonClosedLock) 20548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 20648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (this.reasonClosed == null) 20748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 20848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.reasonClosed = reasonClosed; 20948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 21048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 21148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 21248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 21348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public int getState() 21448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 21548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return this.state; 21648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 21748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood} 218