1 package org.apache.maven.it;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.io.PushbackInputStream;
26 import java.net.ServerSocket;
27 import java.net.Socket;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30
31
32
33
34
35
36 public class TunnelingProxyServer
37 implements Runnable
38 {
39
40 private int port;
41
42 private volatile ServerSocket server;
43
44 private String targetHost;
45
46 private int targetPort;
47
48 private String connectFilter;
49
50 public TunnelingProxyServer( int port, String targetHost, int targetPort, String connectFilter )
51 {
52 this.port = port;
53 this.targetHost = targetHost;
54 this.targetPort = targetPort;
55 this.connectFilter = connectFilter;
56 }
57
58 public int getPort()
59 {
60 return ( server != null ) ? server.getLocalPort() : port;
61 }
62
63 public void start()
64 throws IOException
65 {
66 server = new ServerSocket( port, 4 );
67 new Thread( this ).start();
68 }
69
70 public void stop()
71 throws IOException
72 {
73 if ( server != null )
74 {
75 server.close();
76 server = null;
77 }
78 }
79
80 public void run()
81 {
82 try
83 {
84 while ( true )
85 {
86 new ClientHandler( server.accept() ).start();
87 }
88 }
89 catch ( Exception e )
90 {
91
92 }
93 }
94
95 class ClientHandler
96 extends Thread
97 {
98
99 private Socket client;
100
101 public ClientHandler( Socket client )
102 {
103 this.client = client;
104 }
105
106 public void run()
107 {
108 try
109 {
110 PushbackInputStream is = new PushbackInputStream( client.getInputStream() );
111
112 String dest = null;
113
114 while ( true )
115 {
116 String line = readLine( is );
117 if ( line == null || line.length() <= 0 )
118 {
119 break;
120 }
121 Matcher m = Pattern.compile( "CONNECT +([^:]+:[0-9]+) +.*" ).matcher( line );
122 if ( m.matches() )
123 {
124 dest = m.group( 1 );
125 }
126 }
127
128 OutputStream os = client.getOutputStream();
129
130 if ( dest == null || ( connectFilter != null && !dest.matches( connectFilter ) ) )
131 {
132 os.write( ( "HTTP/1.0 400 Bad request for " + dest + "\r\n\r\n" ).getBytes( "UTF-8" ) );
133 return;
134 }
135
136 os.write( "HTTP/1.0 200 Connection established\r\n\r\n".getBytes( "UTF-8" ) );
137
138 Socket server = new Socket( targetHost, targetPort );
139
140 Thread t1 = new StreamPumper( is, server.getOutputStream() );
141 t1.start();
142 Thread t2 = new StreamPumper( server.getInputStream(), os );
143 t2.start();
144 t1.join();
145 t2.join();
146
147 server.close();
148 }
149 catch ( Exception e )
150 {
151 e.printStackTrace();
152 }
153 finally
154 {
155 try
156 {
157 client.close();
158 }
159 catch ( IOException e )
160 {
161 e.printStackTrace();
162 }
163 }
164 }
165
166 private String readLine( PushbackInputStream is )
167 throws IOException
168 {
169 StringBuilder buffer = new StringBuilder( 1024 );
170
171 while ( true )
172 {
173 int b = is.read();
174 if ( b < 0 )
175 {
176 return null;
177 }
178 else if ( b == '\n' )
179 {
180 break;
181 }
182 else if ( b == '\r' )
183 {
184 b = is.read();
185 if ( b != '\n' )
186 {
187 is.unread( b );
188 }
189 break;
190 }
191 else
192 {
193 buffer.append( (char) b );
194 }
195 }
196
197 return buffer.toString();
198 }
199
200 }
201
202 static class StreamPumper
203 extends Thread
204 {
205
206 private final InputStream is;
207
208 private final OutputStream os;
209
210 public StreamPumper( InputStream is, OutputStream os )
211 {
212 this.is = is;
213 this.os = os;
214 }
215
216 public void run()
217 {
218 try
219 {
220 for ( byte[] buffer = new byte[1024 * 8]; ; )
221 {
222 int n = is.read( buffer );
223 if ( n < 0 )
224 {
225 break;
226 }
227 os.write( buffer, 0, n );
228 }
229 }
230 catch ( IOException e )
231 {
232
233 }
234 finally
235 {
236 try
237 {
238 is.close();
239 }
240 catch ( IOException e )
241 {
242 e.printStackTrace();
243 }
244 try
245 {
246 os.close();
247 }
248 catch ( IOException e )
249 {
250 e.printStackTrace();
251 }
252 }
253 }
254
255 }
256
257 }