source: other-projects/trunk/gs3-release-maker/tasks/sshtaskdef/src/mindbright/ssh/SSHSocketTunnel.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 6.2 KB
Line 
1/******************************************************************************
2 *
3 * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
4 * www.mindbright.se, [email protected]
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 *****************************************************************************
17 * $Author: mats $
18 * $Date: 1999/07/15 14:53:27 $
19 * $Name: rel1-2-1 $
20 *****************************************************************************/
21package mindbright.ssh;
22
23import java.net.*;
24import java.io.*;
25
26public final class SSHSocketTunnel extends SSHTunnel {
27
28 public final static class SSHSocketIS extends InputStream {
29 protected SSHSocketTunnel tunnel;
30 protected SSHSocketIS(SSHSocketTunnel tunnel) {
31 this.tunnel = tunnel;
32 }
33 public int read() throws IOException {
34 byte[] b = new byte[1];
35 if(read(b, 0, 1) == -1)
36 return -1;
37 return (int) b[0];
38 }
39 public int read(byte b[], int off, int len) throws IOException {
40 return tunnel.read(b, off, len);
41 }
42 public void close() throws IOException {
43 tunnel.closein(true);
44 }
45 }
46
47 public final static class SSHSocketOS extends OutputStream {
48 protected SSHSocketTunnel tunnel;
49 protected SSHSocketOS(SSHSocketTunnel tunnel) {
50 this.tunnel = tunnel;
51 }
52 public void write(int b) throws IOException {
53 byte[] ba = new byte[1];
54 ba[0] = (byte) b;
55 tunnel.write(ba, 0, 1);
56 }
57 public void write(byte b[], int off, int len) throws IOException {
58 tunnel.write(b, off, len);
59 }
60 public void close() throws IOException {
61 tunnel.closeout();
62 }
63 }
64
65 Object lock;
66 boolean inputClosePending;
67 boolean inputExplicitClosed;
68 boolean outputClosed;
69 boolean terminated;
70 boolean openFail;
71
72 protected SSHPdu rest;
73 protected SSHSocketIS in;
74 protected SSHSocketOS out;
75 protected InetAddress localAddress;
76
77 protected SSHSocketImpl impl;
78
79 public SSHSocketTunnel(SSHChannelController controller, SSHSocketImpl impl) throws IOException {
80 super(null, controller.newChannelId(), SSH.UNKNOWN_CHAN_NUM, controller);
81
82 this.lock = new Object();
83
84 this.inputClosePending = false;
85 this.inputExplicitClosed = false;
86 this.outputClosed = false;
87 this.terminated = false;
88 this.openFail = false;
89
90 this.txQueue = new SSHPduQueue();
91 this.in = new SSHSocketIS(this);
92 this.out = new SSHSocketOS(this);
93 this.impl = impl;
94 }
95
96 public void start() {
97 synchronized(lock) {
98 lock.notify();
99 }
100 }
101
102 public void openFailure() {
103 openFail = true;
104 start();
105 }
106
107 public int read(byte b[], int off, int len) throws IOException {
108 SSHPdu pdu = null;
109 int actLen;
110
111 synchronized(this) {
112 if(inputExplicitClosed)
113 throw new SocketException("Socket closed");
114 }
115
116 // We reuse the connect-lock since it is only used before we
117 // start, after that it becomes the read-synchronization lock
118 //
119 synchronized(lock) {
120 if(rest != null) {
121 pdu = rest;
122 rest = null;
123 } else if(inputClosePending && txQueue.isEmpty()) {
124 pdu = null;
125 } else {
126 pdu = txQueue.getFirst();
127 }
128
129 if(pdu == null)
130 return -1;
131
132 int rawLen = pdu.rawSize();
133 if(len < rawLen) {
134 rest = pdu;
135 actLen = len;
136 } else {
137 actLen = rawLen;
138 }
139
140 System.arraycopy(pdu.rawData(), pdu.rawOffset(), b, off, actLen);
141
142 if(rest != null) {
143 rest.rawAdjustSize(rawLen - len);
144 }
145 }
146
147 return actLen;
148 }
149
150 public void write(byte b[], int off, int len) throws IOException {
151 SSHPduOutputStream pdu;
152
153 synchronized(this) {
154 if(outputClosed)
155 throw new IOException("Resource temporarily unavailable");
156 }
157
158 pdu = new SSHPduOutputStream(SSH.MSG_CHANNEL_DATA, controller.sndCipher);
159 pdu = (SSHPduOutputStream)prepare(pdu);
160 pdu.writeInt(len);
161 pdu.write(b, off, len);
162 controller.transmit(pdu);
163 }
164
165 public void connect(String host, int port) throws IOException {
166 SSHPduOutputStream respPdu;
167
168 setRemoteDesc(host + ":" + port);
169
170 respPdu = new SSHPduOutputStream(SSH.MSG_PORT_OPEN, controller.sndCipher);
171 controller.addTunnel(this);
172 respPdu.writeInt(channelId);
173 respPdu.writeString(host);
174 respPdu.writeInt(port);
175 respPdu.writeString(localAddress.getHostAddress());
176 controller.transmit(respPdu);
177
178 // Wait for start() to be called (i.e. the channel to be confirmed open)
179 //
180 synchronized(lock) {
181 try {
182 lock.wait();
183 } catch(InterruptedException e) {
184 // !!!
185 }
186 }
187
188 if(openFail)
189 throw new ConnectException("Connection Refused");
190 }
191
192 public void close() throws IOException {
193 closein(true);
194 closeout();
195 }
196
197 public synchronized void closeout() {
198 outputClosed = true;
199 sendInputEOF();
200 }
201
202 public void closein(boolean explicit) {
203 txQueue.release();
204 synchronized(this) {
205 inputClosePending = true;
206 inputExplicitClosed = explicit;
207 sendOutputClosed();
208 }
209 }
210
211 public int available() throws IOException {
212 if(rest != null)
213 return rest.rawSize();
214 else
215 return 0;
216 }
217
218 protected void setLocalAddress(InetAddress localAddress) {
219 this.localAddress = localAddress;
220 }
221
222 public synchronized void checkTermination() {
223 if(sentInputEOF && sentOutputClosed &&
224 receivedInputEOF && receivedOutputClosed) {
225 terminated = true;
226 controller.delTunnel(channelId);
227 impl.factory.closePseudoUser(controller.sshAsClient(), impl);
228 }
229 }
230
231 public synchronized boolean terminated() {
232 return terminated;
233 }
234
235 public void receiveOutputClosed() {
236 super.receiveOutputClosed();
237 closeout();
238 }
239
240 public void receiveInputEOF() {
241 // !!! NOTE: we do not call super's method...
242 receivedInputEOF = true;
243 closein(false);
244 closeout();
245 checkTermination();
246 }
247
248}
Note: See TracBrowser for help on using the repository browser.