comparison src/ch/ethz/ssh2/channel/Channel.java @ 273:91a31873c42a ganymed

start conversion from trilead to ganymed
author Carl Byington <carl@five-ten-sg.com>
date Fri, 18 Jul 2014 11:21:46 -0700
parents
children 071eccdff8ea
comparison
equal deleted inserted replaced
272:ce2f4e397703 273:91a31873c42a
1 /*
2 * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
3 * Please refer to the LICENSE.txt for licensing details.
4 */
5 package ch.ethz.ssh2.channel;
6
7 import java.io.IOException;
8
9 import ch.ethz.ssh2.transport.TransportManager;
10
11 /**
12 * Channel.
13 *
14 * @author Christian Plattner
15 * @version $Id: Channel.java 123 2014-04-12 21:11:47Z dkocher@sudo.ch $
16 */
17 public class Channel
18 {
19 /*
20 * OK. Here is an important part of the JVM Specification:
21 * (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html#22214)
22 *
23 * Any association between locks and variables is purely conventional.
24 * Locking any lock conceptually flushes all variables from a thread's
25 * working memory, and unlocking any lock forces the writing out to main
26 * memory of all variables that the thread has assigned. That a lock may be
27 * associated with a particular object or a class is purely a convention.
28 * (...)
29 *
30 * If a thread uses a particular shared variable only after locking a
31 * particular lock and before the corresponding unlocking of that same lock,
32 * then the thread will read the shared value of that variable from main
33 * memory after the lock operation, if necessary, and will copy back to main
34 * memory the value most recently assigned to that variable before the
35 * unlock operation.
36 *
37 * This, in conjunction with the mutual exclusion rules for locks, suffices
38 * to guarantee that values are correctly transmitted from one thread to
39 * another through shared variables.
40 *
41 * ====> Always keep that in mind when modifying the Channel/ChannelManger
42 * code.
43 *
44 */
45
46 public static final int STATE_OPENING = 1;
47 public static final int STATE_OPEN = 2;
48 public static final int STATE_CLOSED = 4;
49
50 static final int CHANNEL_BUFFER_SIZE = 32 * 1024 * 3 * 2;
51
52 /*
53 * To achieve correctness, the following rules have to be respected when
54 * accessing this object:
55 */
56
57 // These fields can always be read
58 final ChannelManager cm;
59 final ChannelOutputStream stdinStream;
60 final ChannelInputStream stdoutStream;
61 final ChannelInputStream stderrStream;
62
63 // In case this channel belongs to a server-side session.
64 ServerSessionImpl ss;
65
66 // These two fields will only be written while the Channel is in state
67 // STATE_OPENING.
68 // The code makes sure that the two fields are written out when the state is
69 // changing to STATE_OPEN.
70 // Therefore, if you know that the Channel is in state STATE_OPEN, then you
71 // can read these two fields without synchronizing on the Channel. However, make
72 // sure that you get the latest values (e.g., flush caches by synchronizing on any
73 // object). However, to be on the safe side, you can lock the channel.
74
75 int localID = -1;
76 int remoteID = -1;
77
78 /*
79 * Make sure that we never send a data/EOF/WindowChange msg after a CLOSE
80 * msg.
81 *
82 * This is a little bit complicated, but we have to do it in that way, since
83 * we cannot keep a lock on the Channel during the send operation (this
84 * would block sometimes the receiver thread, and, in extreme cases, can
85 * lead to a deadlock on both sides of the connection (senders are blocked
86 * since the receive buffers on the other side are full, and receiver
87 * threads wait for the senders to finish). It all depends on the
88 * implementation on the other side. But we cannot make any assumptions, we
89 * have to assume the worst case. Confused? Just believe me.
90 */
91
92 /*
93 * If you send a message on a channel, then you have to aquire the
94 * "channelSendLock" and check the "closeMessageSent" flag (this variable
95 * may only be accessed while holding the "channelSendLock" !!!
96 *
97 * BTW: NEVER EVER SEND MESSAGES FROM THE RECEIVE THREAD - see explanation
98 * above.
99 */
100
101 final Object channelSendLock = new Object();
102 boolean closeMessageSent = false;
103
104 /*
105 * Stop memory fragmentation by allocating this often used buffer.
106 * May only be used while holding the channelSendLock
107 */
108
109 final byte[] msgWindowAdjust = new byte[9];
110
111 // If you access (read or write) any of the following fields, then you have
112 // to synchronize on the channel.
113
114 int state = STATE_OPENING;
115
116 boolean closeMessageRecv = false;
117
118 /* This is a stupid implementation. At the moment we can only wait
119 * for one pending request per channel.
120 */
121 int successCounter = 0;
122 int failedCounter = 0;
123
124 int localWindow = 0; /* locally, we use a small window, < 2^31 */
125 long remoteWindow = 0; /* long for readable 2^32 - 1 window support */
126
127 int localMaxPacketSize = -1;
128 int remoteMaxPacketSize = -1;
129
130 final byte[] stdoutBuffer = new byte[CHANNEL_BUFFER_SIZE];
131 final byte[] stderrBuffer = new byte[CHANNEL_BUFFER_SIZE];
132
133 int stdoutReadpos = 0;
134 int stdoutWritepos = 0;
135 int stderrReadpos = 0;
136 int stderrWritepos = 0;
137
138 boolean EOF = false;
139
140 Integer exit_status;
141
142 String exit_signal;
143
144 // we keep the x11 cookie so that this channel can be closed when this
145 // specific x11 forwarding gets stopped
146
147 String hexX11FakeCookie;
148
149 // reasonClosed is special, since we sometimes need to access it
150 // while holding the channelSendLock.
151 // We protect it with a private short term lock.
152
153 private final Object reasonClosedLock = new Object();
154 private IOException reasonClosed = null;
155
156 public Channel(ChannelManager cm)
157 {
158 this.cm = cm;
159
160 this.localWindow = CHANNEL_BUFFER_SIZE;
161 this.localMaxPacketSize = TransportManager.MAX_PACKET_SIZE;
162
163 this.stdinStream = new ChannelOutputStream(this);
164 this.stdoutStream = new ChannelInputStream(this, false);
165 this.stderrStream = new ChannelInputStream(this, true);
166 }
167
168 /* Methods to allow access from classes outside of this package */
169
170 public ChannelInputStream getStderrStream()
171 {
172 return stderrStream;
173 }
174
175 public ChannelOutputStream getStdinStream()
176 {
177 return stdinStream;
178 }
179
180 public ChannelInputStream getStdoutStream()
181 {
182 return stdoutStream;
183 }
184
185 public String getExitSignal()
186 {
187 synchronized (this)
188 {
189 return exit_signal;
190 }
191 }
192
193 public Integer getExitStatus()
194 {
195 synchronized (this)
196 {
197 return exit_status;
198 }
199 }
200
201 public IOException getReasonClosed()
202 {
203 synchronized (reasonClosedLock)
204 {
205 return reasonClosed;
206 }
207 }
208
209 public void setReasonClosed(IOException e)
210 {
211 synchronized (reasonClosedLock)
212 {
213 this.reasonClosed = e;
214 }
215 }
216
217 public int getState()
218 {
219 return this.state;
220 }
221 }