KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > http > HttpTunnel


1 // ========================================================================
2
// $Id: HttpTunnel.java,v 1.11 2005/10/05 11:14:37 gregwilkins Exp $
3
// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.http;
17
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.io.InterruptedIOException JavaDoc;
21 import java.io.OutputStream JavaDoc;
22 import java.net.Socket JavaDoc;
23
24 import org.apache.commons.logging.Log;
25 import org.mortbay.log.LogFactory;
26 import org.mortbay.util.IO;
27 import org.mortbay.util.LogSupport;
28
29 /* ------------------------------------------------------------ */
30 /** HTTP Tunnel.
31  * A HTTP Tunnel can be used to take over a HTTP connection in order to
32  * tunnel another protocol over it. The prime example is the CONNECT method
33  * handled by the ProxyHandler to setup a SSL tunnel between the client and
34  * the real server.
35  *
36  * @see HttpConnection
37  * @version $Revision: 1.11 $
38  * @author Greg Wilkins (gregw)
39  */

40 public class HttpTunnel
41 {
42     private static Log log= LogFactory.getLog(HttpTunnel.class);
43
44     private Thread JavaDoc _thread;
45     private int _timeoutMs;
46     private Socket JavaDoc _socket;
47     private InputStream JavaDoc _sIn;
48     private OutputStream JavaDoc _sOut;
49     private InputStream JavaDoc _in;
50     private OutputStream JavaDoc _out;
51
52     /* ------------------------------------------------------------ */
53     /** Constructor.
54      */

55     protected HttpTunnel()
56     {
57     }
58     
59     /* ------------------------------------------------------------ */
60     /** Constructor.
61      * @param socket The tunnel socket.
62      * @param timeoutMs The maximum time to wait for a read on the tunnel. Note that
63      * sotimer exceptions are ignored by the tunnel.
64      * @param in Alternative input stream or null if using normal socket stream
65      * @param out Alternative output stream or null if using normal socket stream
66      * @param timeoutMs
67      * @throws IOException
68      */

69     public HttpTunnel(Socket JavaDoc socket, InputStream JavaDoc in, OutputStream JavaDoc out) throws IOException JavaDoc
70     {
71         _socket= socket;
72         _sIn=in;
73         _sOut=out;
74         if (_sIn==null)
75             _sIn=_socket.getInputStream();
76         if (_sOut==null)
77             _sOut=socket.getOutputStream();
78         _timeoutMs=30000;
79     }
80
81     /* ------------------------------------------------------------ */
82     /** handle method.
83      * This method is called by the HttpConnection.handleNext() method if
84      * this HttpTunnel has been set on that connection.
85      * The default implementation of this method copies between the HTTP
86      * socket and the socket passed in the constructor.
87      * @param in
88      * @param out
89      */

90     public void handle(InputStream JavaDoc in, OutputStream JavaDoc out)
91     {
92         Copy copy= new Copy();
93         _in= in;
94         _out= out;
95         try
96         {
97             _thread= Thread.currentThread();
98             copy.start();
99
100             copydata(_sIn, _out);
101         }
102         catch (Exception JavaDoc e)
103         {
104             LogSupport.ignore(log, e);
105         }
106         finally
107         {
108             try
109             {
110                 _in.close();
111                 if (_socket!=null)
112                 {
113                     _socket.shutdownOutput();
114                     _socket.close();
115                 }
116                 else
117                 {
118                     _sIn.close();
119                     _sOut.close();
120                 }
121             }
122             catch (Exception JavaDoc e)
123             {
124                 LogSupport.ignore(log, e);
125             }
126             copy.interrupt();
127         }
128     }
129
130     /* ------------------------------------------------------------ */
131     private void copydata(InputStream JavaDoc in, OutputStream JavaDoc out) throws java.io.IOException JavaDoc
132     {
133         long timestamp= 0;
134         long byteCount = 0;
135         while (true)
136         {
137             try
138             {
139                 byteCount = copyBytes(in, out,-1);
140                 timestamp= 0;
141                 if (byteCount == -1) {
142                     return;
143                 }
144             }
145             catch (InterruptedIOException JavaDoc e)
146             {
147                 LogSupport.ignore(log, e);
148                 if (timestamp == 0)
149                     timestamp= System.currentTimeMillis();
150                 else if (_timeoutMs > 0 && (System.currentTimeMillis() - timestamp) > _timeoutMs)
151                     throw e;
152             }
153         }
154     }
155     
156
157     /* ------------------------------------------------------------------- */
158     /** Copy Stream in to Stream for byteCount bytes or until EOF or exception.
159       * @return Copied bytes count or -1 if no bytes were read *and* EOF was reached
160     */

161     public static int copyBytes(InputStream JavaDoc in,
162                                 OutputStream JavaDoc out,
163                                 long byteCount)
164          throws IOException JavaDoc
165     {
166         byte buffer[] = new byte[IO.bufferSize];
167         int len=IO.bufferSize;
168         int totalCount=0;
169         
170         if (byteCount>=0)
171         {
172             totalCount=(int)byteCount;
173             while (byteCount>0)
174             {
175                 try {
176                     if (byteCount<IO.bufferSize)
177                         len=in.read(buffer,0,(int)byteCount);
178                     else
179                         len=in.read(buffer,0,IO.bufferSize);
180                     if (len==-1 && totalCount==byteCount)
181                         totalCount=(int)byteCount - 1;
182                 } catch (InterruptedIOException JavaDoc e) {
183                     if (totalCount==byteCount)
184                         throw e;
185                     LogSupport.ignore(log, e);
186                     len=0;
187                 }
188                 
189                 if (len<=0)
190                     break;
191                 
192                 byteCount -= len;
193                 out.write(buffer,0,len);
194             }
195             totalCount -= byteCount;
196         }
197         else
198         {
199             while (len>0)
200             {
201                 try {
202                     len=in.read(buffer,0,IO.bufferSize);
203                     if (len==-1 && totalCount==0)
204                         totalCount=-1;
205                 } catch (InterruptedIOException JavaDoc e) {
206                     if (totalCount==0)
207                         throw e;
208                     LogSupport.ignore(log, e);
209                     len=0;
210                 }
211                 if (len>0) {
212                     out.write(buffer,0,len);
213                     totalCount += len;
214                 }
215             }
216         }
217         return totalCount;
218     }
219     
220
221     /* ------------------------------------------------------------ */
222     /* ------------------------------------------------------------ */
223     /** Copy thread.
224      * Helper thread to copy from the HTTP input to the sockets output
225      */

226     private class Copy extends Thread JavaDoc
227     {
228         public void run()
229         {
230             try
231             {
232                 copydata(_in, _sOut);
233             }
234             catch (Exception JavaDoc e)
235             {
236                 LogSupport.ignore(log, e);
237             }
238             finally
239             {
240                 try
241                 {
242                     _out.close();
243                     if (_socket!=null)
244                     {
245                         _socket.shutdownInput();
246                         _socket.close();
247                     }
248                     else
249                     {
250                         _sOut.close();
251                         _sIn.close();
252                     }
253                 }
254                 catch (Exception JavaDoc e)
255                 {
256                     LogSupport.ignore(log, e);
257                 }
258                 _thread.interrupt();
259             }
260         }
261     }
262
263
264     /* ------------------------------------------------------------ */
265     /**
266      * @return Returns the socket.
267      */

268     public Socket JavaDoc getSocket()
269     {
270         return _socket;
271     }
272
273     /* ------------------------------------------------------------ */
274     /**
275      * @return Returns the timeoutMs.
276      */

277     public int getTimeoutMs()
278     {
279         return _timeoutMs;
280     }
281
282     /* ------------------------------------------------------------ */
283     /**
284      * @param timeoutMs The timeoutMs to set.
285      */

286     public void setTimeoutMs(int timeoutMs)
287     {
288         _timeoutMs = timeoutMs;
289     }
290
291 }
292
Popular Tags