blob: 22cf82aed64814ec60dbb16c5cb49d0f2483395d [file] [log] [blame]
duke6e45e102007-12-01 00:00:00 +00001/*
ohair2283b9d2010-05-25 15:58:33 -07002 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
duke6e45e102007-12-01 00:00:00 +00003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
ohair2283b9d2010-05-25 15:58:33 -070019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
duke6e45e102007-12-01 00:00:00 +000022 */
23
24/* @test
25 * @bug 4920526
26 * @summary Needs per connection proxy support for URLs
27 * @library ../../../sun/net/www/httptest/
28 * @build ClosedChannelList HttpServer HttpTransaction HttpCallback
darcyff8ea172009-12-03 18:19:10 -080029 * @compile PerConnectionProxy.java
duke6e45e102007-12-01 00:00:00 +000030 * @run main/othervm -Dhttp.proxyHost=inexistant -Dhttp.proxyPort=8080 PerConnectionProxy
31 */
32
33import java.net.*;
34import java.io.*;
35import sun.net.www.*;
36
37public class PerConnectionProxy implements HttpCallback {
38 static HttpServer server;
39
40 public void request (HttpTransaction req) {
41 req.setResponseEntityBody ("Hello .");
42 try {
43 req.sendResponse (200, "Ok");
44 req.orderlyClose();
45 } catch (IOException e) {
46 }
47 }
48
49 public static void main(String[] args) {
50 try {
51 server = new HttpServer (new PerConnectionProxy(), 1, 10, 0);
52 ProxyServer pserver = new ProxyServer(InetAddress.getByName("localhost"), server.getLocalPort());
53 // start proxy server
54 new Thread(pserver).start();
55
56 URL url = new URL("http://localhost:"+server.getLocalPort());
57
58 // for non existing proxy expect an IOException
59 try {
60 InetSocketAddress isa = InetSocketAddress.createUnresolved("inexistent", 8080);
61 Proxy proxy = new Proxy(Proxy.Type.HTTP, isa);
62 HttpURLConnection urlc = (HttpURLConnection)url.openConnection (proxy);
63 InputStream is = urlc.getInputStream ();
64 is.close();
65 throw new RuntimeException("non existing per connection proxy should lead to IOException");
66 } catch (IOException ioex) {
67 // expected
68 }
69
70 // for NO_PROXY, expect direct connection
71 try {
72 HttpURLConnection urlc = (HttpURLConnection)url.openConnection (Proxy.NO_PROXY);
73 int respCode = urlc.getResponseCode();
74 urlc.disconnect();
75 } catch (IOException ioex) {
76 throw new RuntimeException("direct connection should succeed :"+ioex.getMessage());
77 }
78
79 // for a normal proxy setting expect to see connection
80 // goes through that proxy
81 try {
82 InetSocketAddress isa = InetSocketAddress.createUnresolved("localhost", pserver.getPort());
83 Proxy p = new Proxy(Proxy.Type.HTTP, isa);
84 HttpURLConnection urlc = (HttpURLConnection)url.openConnection (p);
85 int respCode = urlc.getResponseCode();
86 urlc.disconnect();
87 } catch (IOException ioex) {
88 throw new RuntimeException("connection through a local proxy should succeed :"+ioex.getMessage());
89 }
90
91 } catch (Exception e) {
92 throw new RuntimeException(e);
93 } finally {
94 if (server != null) {
95 server.terminate();
96 }
97 }
98
99 }
100
101 static class ProxyServer extends Thread {
102 private static ServerSocket ss = null;
103
104 // client requesting for a tunnel
105 private Socket clientSocket = null;
106
107 /*
108 * Origin server's address and port that the client
109 * wants to establish the tunnel for communication.
110 */
111 private InetAddress serverInetAddr;
112 private int serverPort;
113
114 public ProxyServer(InetAddress server, int port) throws IOException {
115 serverInetAddr = server;
116 serverPort = port;
117 ss = new ServerSocket(0);
118 }
119
120 public void run() {
121 try {
122 clientSocket = ss.accept();
123 processRequests();
124 } catch (Exception e) {
125 System.out.println("Proxy Failed: " + e);
126 e.printStackTrace();
127 try {
128 ss.close();
129 }
130 catch (IOException excep) {
131 System.out.println("ProxyServer close error: " + excep);
132 excep.printStackTrace();
133 }
134 }
135 }
136
137 private void processRequests() throws Exception {
138 // connection set to the tunneling mode
139
140 Socket serverSocket = new Socket(serverInetAddr, serverPort);
141 ProxyTunnel clientToServer = new ProxyTunnel(
142 clientSocket, serverSocket);
143 ProxyTunnel serverToClient = new ProxyTunnel(
144 serverSocket, clientSocket);
145 clientToServer.start();
146 serverToClient.start();
147 System.out.println("Proxy: Started tunneling.......");
148
149 clientToServer.join();
150 serverToClient.join();
151 System.out.println("Proxy: Finished tunneling........");
152
153 clientToServer.close();
154 serverToClient.close();
155
156 }
157
158 /**
159***************************************************************
160* helper methods follow
161***************************************************************
162*/
163 public int getPort() {
164 return ss.getLocalPort();
165 }
166 /*
167 * This inner class provides unidirectional data flow through the sockets
168 * by continuously copying bytes from the input socket onto the output
169 * socket, until both sockets are open and EOF has not been received.
170 */
171 static class ProxyTunnel extends Thread {
172 Socket sockIn;
173 Socket sockOut;
174 InputStream input;
175 OutputStream output;
176
177 public ProxyTunnel(Socket sockIn, Socket sockOut)
178 throws Exception {
179 this.sockIn = sockIn;
180 this.sockOut = sockOut;
181 input = sockIn.getInputStream();
182 output = sockOut.getOutputStream();
183 }
184
185 public void run() {
186 int BUFFER_SIZE = 400;
187 byte[] buf = new byte[BUFFER_SIZE];
188 int bytesRead = 0;
189 int count = 0; // keep track of the amount of data transfer
190
191 try {
192 while ((bytesRead = input.read(buf)) >= 0) {
193 output.write(buf, 0, bytesRead);
194 output.flush();
195 count += bytesRead;
196 }
197 } catch (IOException e) {
198 /*
199 * The peer end has closed the connection
200 * we will close the tunnel
201 */
202 close();
203 }
204 }
205
206 public void close() {
207 try {
208 if (!sockIn.isClosed())
209 sockIn.close();
210 if (!sockOut.isClosed())
211 sockOut.close();
212 } catch (IOException ignored) { }
213 }
214 }
215
216 }
217}