< prev index next >
test/jdk/java/net/Socket/HttpProxy.java
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -21,15 +21,16 @@
* questions.
*/
/*
* @test
- * @bug 6370908
+ * @bug 6370908 8220663
* @summary Add support for HTTP_CONNECT proxy in Socket class
* @modules java.base/sun.net.www
* @run main HttpProxy
* @run main/othervm -Djava.net.preferIPv4Stack=true HttpProxy
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true HttpProxy
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -38,23 +39,27 @@
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.List;
import sun.net.www.MessageHeader;
public class HttpProxy {
final String proxyHost;
final int proxyPort;
static final int SO_TIMEOUT = 15000;
public static void main(String[] args) throws Exception {
String host;
int port;
+ ConnectProxyTunnelServer proxy = null;
if (args.length == 0) {
// Start internal proxy
- ConnectProxyTunnelServer proxy = new ConnectProxyTunnelServer();
+ proxy = new ConnectProxyTunnelServer();
proxy.start();
host = "localhost";
port = proxy.getLocalPort();
out.println("Running with internal proxy: " + host + ":" + port);
} else if (args.length == 2) {
@@ -64,12 +69,17 @@
} else {
System.err.println("Usage: java HttpProxy [<proxy host> <proxy port>]");
return;
}
+ try {
HttpProxy p = new HttpProxy(host, port);
p.test();
+ } finally {
+ if (proxy != null)
+ proxy.close();
+ }
}
public HttpProxy(String proxyHost, int proxyPort) {
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
@@ -77,18 +87,27 @@
void test() throws Exception {
InetSocketAddress proxyAddress = new InetSocketAddress(proxyHost, proxyPort);
Proxy httpProxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
- try (ServerSocket ss = new ServerSocket(0);
- Socket sock = new Socket(httpProxy)) {
+ try (ServerSocket ss = new ServerSocket(0)) {
+ List<InetSocketAddress> externalAddresses = new ArrayList<>();
+ externalAddresses.add(
+ new InetSocketAddress(InetAddress.getLocalHost(), ss.getLocalPort()));
+
+ if (!"true".equals(System.getProperty("java.net.preferIPv4Stack"))) {
+ byte[] bytes = new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+ var address = InetAddress.getByAddress(bytes);
+ externalAddresses.add(
+ new InetSocketAddress(address, ss.getLocalPort()));
+ }
+
+ for (SocketAddress externalAddress : externalAddresses) {
+ try (Socket sock = new Socket(httpProxy)) {
sock.setSoTimeout(SO_TIMEOUT);
sock.setTcpNoDelay(false);
- InetSocketAddress externalAddress =
- new InetSocketAddress(InetAddress.getLocalHost(), ss.getLocalPort());
-
out.println("Trying to connect to server socket on " + externalAddress);
sock.connect(externalAddress);
try (Socket externalSock = ss.accept()) {
// perform some simple checks
check(sock.isBound(), "Socket is not bound");
@@ -100,17 +119,19 @@
simpleDataExchange(sock, externalSock);
}
}
}
+ }
+ }
static void check(boolean condition, String message) {
if (!condition) out.println(message);
}
static Exception unexpected(Exception e) {
- out.println("Unexcepted Exception: " + e);
+ out.println("Unexpected Exception: " + e);
e.printStackTrace();
return e;
}
// performs a simple exchange of data between the two sockets
@@ -162,26 +183,34 @@
int i1 = (int)b1 & 0xFF;
int i2 = (int)b2 & 0xFF;
return i1 * 256 + i2;
}
- static class ConnectProxyTunnelServer extends Thread {
+ static class ConnectProxyTunnelServer extends Thread implements AutoCloseable {
private final ServerSocket ss;
+ private volatile boolean closed;
public ConnectProxyTunnelServer() throws IOException {
ss = new ServerSocket(0);
}
@Override
public void run() {
+ try {
+ while (!closed) {
try (Socket clientSocket = ss.accept()) {
processRequest(clientSocket);
+ }
+ }
} catch (Exception e) {
+ if (!closed) {
out.println("Proxy Failed: " + e);
e.printStackTrace();
+ }
} finally {
+ if (!closed)
try { ss.close(); } catch (IOException x) { unexpected(x); }
}
}
/**
@@ -189,20 +218,26 @@
*/
public int getLocalPort() {
return ss.getLocalPort();
}
+ @Override
+ public void close() throws Exception {
+ closed = true;
+ ss.close();
+ }
+
/*
* Processes the CONNECT request
*/
private void processRequest(Socket clientSocket) throws Exception {
MessageHeader mheader = new MessageHeader(clientSocket.getInputStream());
String statusLine = mheader.getValue(0);
if (!statusLine.startsWith("CONNECT")) {
out.println("proxy server: processes only "
- + "CONNECT method requests, recieved: "
+ + "CONNECT method requests, received: "
+ statusLine);
return;
}
// retrieve the host and port info from the status-line
@@ -244,16 +279,21 @@
try {
int starti = connectStr.indexOf(' ');
int endi = connectStr.lastIndexOf(' ');
String connectInfo = connectStr.substring(starti+1, endi).trim();
// retrieve server name and port
- endi = connectInfo.indexOf(':');
+ endi = connectInfo.lastIndexOf(':');
String name = connectInfo.substring(0, endi);
+ if (name.startsWith("[")) {
+ assert name.endsWith("]") : "name:" + name;
+ assert name.contains(":") : "name:" + name;
+ name = name.substring(1, name.length() - 1);
+ }
int port = Integer.parseInt(connectInfo.substring(endi+1));
return new InetSocketAddress(name, port);
} catch (Exception e) {
- out.println("Proxy recieved a request: " + connectStr);
+ out.println("Proxy received a request: " + connectStr);
throw unexpected(e);
}
}
}
< prev index next >