0N/A/*
2362N/A * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/* @test
0N/A * @bug 4920526
0N/A * @summary Needs per connection proxy support for URLs
0N/A * @library ../../../sun/net/www/httptest/
0N/A * @build ClosedChannelList HttpServer HttpTransaction HttpCallback
1952N/A * @compile PerConnectionProxy.java
0N/A * @run main/othervm -Dhttp.proxyHost=inexistant -Dhttp.proxyPort=8080 PerConnectionProxy
0N/A */
0N/A
0N/Aimport java.net.*;
0N/Aimport java.io.*;
0N/Aimport sun.net.www.*;
0N/A
0N/Apublic class PerConnectionProxy implements HttpCallback {
0N/A static HttpServer server;
0N/A
0N/A public void request (HttpTransaction req) {
0N/A req.setResponseEntityBody ("Hello .");
0N/A try {
0N/A req.sendResponse (200, "Ok");
0N/A req.orderlyClose();
0N/A } catch (IOException e) {
0N/A }
0N/A }
0N/A
0N/A public static void main(String[] args) {
0N/A try {
0N/A server = new HttpServer (new PerConnectionProxy(), 1, 10, 0);
0N/A ProxyServer pserver = new ProxyServer(InetAddress.getByName("localhost"), server.getLocalPort());
0N/A // start proxy server
0N/A new Thread(pserver).start();
0N/A
0N/A URL url = new URL("http://localhost:"+server.getLocalPort());
0N/A
0N/A // for non existing proxy expect an IOException
0N/A try {
0N/A InetSocketAddress isa = InetSocketAddress.createUnresolved("inexistent", 8080);
0N/A Proxy proxy = new Proxy(Proxy.Type.HTTP, isa);
0N/A HttpURLConnection urlc = (HttpURLConnection)url.openConnection (proxy);
0N/A InputStream is = urlc.getInputStream ();
0N/A is.close();
0N/A throw new RuntimeException("non existing per connection proxy should lead to IOException");
0N/A } catch (IOException ioex) {
0N/A // expected
0N/A }
0N/A
0N/A // for NO_PROXY, expect direct connection
0N/A try {
0N/A HttpURLConnection urlc = (HttpURLConnection)url.openConnection (Proxy.NO_PROXY);
0N/A int respCode = urlc.getResponseCode();
0N/A urlc.disconnect();
0N/A } catch (IOException ioex) {
0N/A throw new RuntimeException("direct connection should succeed :"+ioex.getMessage());
0N/A }
0N/A
0N/A // for a normal proxy setting expect to see connection
0N/A // goes through that proxy
0N/A try {
0N/A InetSocketAddress isa = InetSocketAddress.createUnresolved("localhost", pserver.getPort());
0N/A Proxy p = new Proxy(Proxy.Type.HTTP, isa);
0N/A HttpURLConnection urlc = (HttpURLConnection)url.openConnection (p);
0N/A int respCode = urlc.getResponseCode();
0N/A urlc.disconnect();
0N/A } catch (IOException ioex) {
0N/A throw new RuntimeException("connection through a local proxy should succeed :"+ioex.getMessage());
0N/A }
0N/A
0N/A } catch (Exception e) {
0N/A throw new RuntimeException(e);
0N/A } finally {
0N/A if (server != null) {
0N/A server.terminate();
0N/A }
0N/A }
0N/A
0N/A }
0N/A
0N/A static class ProxyServer extends Thread {
0N/A private static ServerSocket ss = null;
0N/A
0N/A // client requesting for a tunnel
0N/A private Socket clientSocket = null;
0N/A
0N/A /*
0N/A * Origin server's address and port that the client
0N/A * wants to establish the tunnel for communication.
0N/A */
0N/A private InetAddress serverInetAddr;
0N/A private int serverPort;
0N/A
0N/A public ProxyServer(InetAddress server, int port) throws IOException {
0N/A serverInetAddr = server;
0N/A serverPort = port;
0N/A ss = new ServerSocket(0);
0N/A }
0N/A
0N/A public void run() {
0N/A try {
0N/A clientSocket = ss.accept();
0N/A processRequests();
0N/A } catch (Exception e) {
0N/A System.out.println("Proxy Failed: " + e);
0N/A e.printStackTrace();
0N/A try {
0N/A ss.close();
0N/A }
0N/A catch (IOException excep) {
0N/A System.out.println("ProxyServer close error: " + excep);
0N/A excep.printStackTrace();
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void processRequests() throws Exception {
0N/A // connection set to the tunneling mode
0N/A
0N/A Socket serverSocket = new Socket(serverInetAddr, serverPort);
0N/A ProxyTunnel clientToServer = new ProxyTunnel(
0N/A clientSocket, serverSocket);
0N/A ProxyTunnel serverToClient = new ProxyTunnel(
0N/A serverSocket, clientSocket);
0N/A clientToServer.start();
0N/A serverToClient.start();
0N/A System.out.println("Proxy: Started tunneling.......");
0N/A
0N/A clientToServer.join();
0N/A serverToClient.join();
0N/A System.out.println("Proxy: Finished tunneling........");
0N/A
0N/A clientToServer.close();
0N/A serverToClient.close();
0N/A
0N/A }
0N/A
0N/A /**
0N/A***************************************************************
0N/A* helper methods follow
0N/A***************************************************************
0N/A*/
0N/A public int getPort() {
0N/A return ss.getLocalPort();
0N/A }
0N/A /*
0N/A * This inner class provides unidirectional data flow through the sockets
0N/A * by continuously copying bytes from the input socket onto the output
0N/A * socket, until both sockets are open and EOF has not been received.
0N/A */
0N/A static class ProxyTunnel extends Thread {
0N/A Socket sockIn;
0N/A Socket sockOut;
0N/A InputStream input;
0N/A OutputStream output;
0N/A
0N/A public ProxyTunnel(Socket sockIn, Socket sockOut)
0N/A throws Exception {
0N/A this.sockIn = sockIn;
0N/A this.sockOut = sockOut;
0N/A input = sockIn.getInputStream();
0N/A output = sockOut.getOutputStream();
0N/A }
0N/A
0N/A public void run() {
0N/A int BUFFER_SIZE = 400;
0N/A byte[] buf = new byte[BUFFER_SIZE];
0N/A int bytesRead = 0;
0N/A int count = 0; // keep track of the amount of data transfer
0N/A
0N/A try {
0N/A while ((bytesRead = input.read(buf)) >= 0) {
0N/A output.write(buf, 0, bytesRead);
0N/A output.flush();
0N/A count += bytesRead;
0N/A }
0N/A } catch (IOException e) {
0N/A /*
0N/A * The peer end has closed the connection
0N/A * we will close the tunnel
0N/A */
0N/A close();
0N/A }
0N/A }
0N/A
0N/A public void close() {
0N/A try {
0N/A if (!sockIn.isClosed())
0N/A sockIn.close();
0N/A if (!sockOut.isClosed())
0N/A sockOut.close();
0N/A } catch (IOException ignored) { }
0N/A }
0N/A }
0N/A
0N/A }
0N/A}