8223880: Update sun/net/ftp/FtpURL.java and sun/net/ftp/FtpURLConnectionLeak.java to work with IPv6 addresses
Summary: This fix updates three tests: sun/net/ftp/FtpURL.java, sun/net/ftp/FtpURLConnectionLeak.java, and sun/net/ftp/FtpGetContent.java, to work with IPv6 addresses
Reviewed-by: chegar, aeubanks, vtewari
--- a/test/jdk/sun/net/ftp/FtpGetContent.java Wed May 15 19:09:54 2019 +0100
+++ b/test/jdk/sun/net/ftp/FtpGetContent.java Wed May 15 19:34:34 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -28,6 +28,8 @@
* @test
* @bug 4255280
* @summary URL.getContent() loses first six bytes for ftp URLs
+ * @run main FtpGetContent
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true FtpGetContent
*/
public class FtpGetContent {
@@ -38,11 +40,12 @@
*/
private class FtpServer extends Thread {
- private ServerSocket server;
+ private final ServerSocket server;
private int port;
private boolean done = false;
private boolean portEnabled = true;
private boolean pasvEnabled = true;
+ private boolean extendedEnabled = true;
private String username;
private String password;
private String cwd;
@@ -77,9 +80,10 @@
private final int NLST = 15;
private final int RNFR = 16;
private final int RNTO = 17;
+ private final int EPSV = 18;
String[] cmds = { "USER", "PASS", "CWD", "CDUP", "PWD", "TYPE",
"NOOP", "RETR", "PASV", "PORT", "LIST", "REIN",
- "QUIT", "STOR", "NLST", "RNFR", "RNTO" };
+ "QUIT", "STOR", "NLST", "RNFR", "RNTO", "EPSV"};
private String arg = null;
private ServerSocket pasv = null;
private int data_port = 0;
@@ -91,6 +95,7 @@
*/
private int parseCmd(String cmd) {
+ System.out.println("FTP server received command: " + cmd);
if (cmd == null || cmd.length() < 3)
return ERROR;
int blank = cmd.indexOf(' ');
@@ -248,14 +253,42 @@
case PWD:
out.println("257 \"" + cwd + "\" is current directory");
break;
+ case EPSV:
+ if (!extendedEnabled || !pasvEnabled) {
+ out.println("500 EPSV is disabled, " +
+ "use PORT instead.");
+ continue;
+ }
+ if (!(server.getInetAddress() instanceof Inet6Address)) {
+ // pretend EPSV is not implemented
+ out.println("500 '" + str + "': command not understood.");
+ break;
+ }
+ if ("all".equalsIgnoreCase(arg)) {
+ out.println("200 EPSV ALL command successful.");
+ continue;
+ }
+ try {
+ if (pasv == null)
+ pasv = new ServerSocket(0, 0, server.getInetAddress());
+ int port = pasv.getLocalPort();
+ out.println("229 Entering Extended" +
+ " Passive Mode (|||" + port + "|)");
+ } catch (IOException ssex) {
+ out.println("425 Can't build data connection:" +
+ " Connection refused.");
+ }
+ break;
case PASV:
if (!pasvEnabled) {
out.println("500 PASV is disabled, use PORT instead.");
continue;
}
try {
- if (pasv == null)
- pasv = new ServerSocket(0);
+ if (pasv == null) {
+ pasv = new ServerSocket();
+ pasv.bind(new InetSocketAddress("127.0.0.1", 0));
+ }
int port = pasv.getLocalPort();
out.println("227 Entering Passive Mode (127,0,0,1," +
(port >> 8) + "," + (port & 0xff) +")");
@@ -367,10 +400,16 @@
}
public FtpServer(int port) {
+ this(null, 0);
+ }
+
+ public FtpServer(InetAddress address, int port) {
this.port = port;
try {
- server = new ServerSocket(port);
+ server = new ServerSocket();
+ server.bind(new InetSocketAddress(address, port));
} catch (IOException e) {
+ throw new RuntimeException(e);
}
}
@@ -384,6 +423,16 @@
return 0;
}
+ public String getAuthority() {
+ InetAddress address = server.getInetAddress();
+ String hostaddr = address.isAnyLocalAddress()
+ ? "localhost" : address.getHostAddress();
+ if (hostaddr.indexOf(':') > -1) {
+ hostaddr = "[" + hostaddr +"]";
+ }
+ return hostaddr + ":" + getPort();
+ }
+
/**
* A way to tell the server that it can stop.
*/
@@ -452,14 +501,16 @@
public FtpGetContent() throws Exception {
FtpServer server = null;
try {
- server = new FtpServer(0);
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+ server = new FtpServer(loopback, 0);
server.start();
- int port = server.getPort();
+ String authority = server.getAuthority();
// Now let's check the URL handler
- URL url = new URL("ftp://localhost:" + port + "/pub/BigFile");
- InputStream stream = (InputStream)url.getContent();
+ URL url = new URL("ftp://" + authority + "/pub/BigFile");
+ InputStream stream = (InputStream)url.openConnection(Proxy.NO_PROXY)
+ .getContent();
byte[] buffer = new byte[1024];
int totalBytes = 0;
int bytesRead = stream.read(buffer);
--- a/test/jdk/sun/net/ftp/FtpURL.java Wed May 15 19:09:54 2019 +0100
+++ b/test/jdk/sun/net/ftp/FtpURL.java Wed May 15 19:34:34 2019 +0100
@@ -23,11 +23,16 @@
import java.io.*;
import java.net.*;
+import jdk.test.lib.net.IPSupport;
/*
* @test
* @bug 4398880
* @summary FTP URL processing modified to conform to RFC 1738
+ * @library /test/lib
+ * @run main/othervm FtpURL
+ * @run main/othervm -Djava.net.preferIPv4Stack=true FtpURL
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true FtpURL
*/
public class FtpURL {
@@ -41,6 +46,7 @@
private boolean done = false;
private boolean portEnabled = true;
private boolean pasvEnabled = true;
+ private boolean extendedEnabled = true;
private String username;
private String password;
private String cwd;
@@ -75,9 +81,10 @@
private final int NLST = 15;
private final int RNFR = 16;
private final int RNTO = 17;
+ private final int EPSV = 18;
String[] cmds = { "USER", "PASS", "CWD", "CDUP", "PWD", "TYPE",
"NOOP", "RETR", "PASV", "PORT", "LIST", "REIN",
- "QUIT", "STOR", "NLST", "RNFR", "RNTO" };
+ "QUIT", "STOR", "NLST", "RNFR", "RNTO", "EPSV" };
private String arg = null;
private ServerSocket pasv = null;
private int data_port = 0;
@@ -89,6 +96,7 @@
*/
private int parseCmd(String cmd) {
+ System.out.println("Received command: " + cmd);
if (cmd == null || cmd.length() < 3)
return ERROR;
int blank = cmd.indexOf(' ');
@@ -127,7 +135,7 @@
/**
* Open the data socket with the client. This can be the
- * result of a "PASV" or "PORT" command.
+ * result of a "EPSV", "PASV" or "PORT" command.
*/
protected OutputStream getOutDataStream() {
@@ -247,6 +255,33 @@
case PWD:
out.println("257 \"" + cwd + "\" is current directory");
break;
+ case EPSV:
+ if (!extendedEnabled || !pasvEnabled) {
+ out.println("500 EPSV is disabled, " +
+ "use PORT instead.");
+ continue;
+ }
+ if (!(server.getInetAddress() instanceof Inet6Address)) {
+ // pretend EPSV is not implemented
+ out.println("500 '" + str + "': command not understood.");
+ break;
+ }
+ if ("all".equalsIgnoreCase(arg)) {
+ out.println("200 EPSV ALL command successful.");
+ continue;
+ }
+ try {
+ if (pasv == null)
+ pasv = new ServerSocket(0, 0, server.getInetAddress());
+ int port = pasv.getLocalPort();
+ out.println("229 Entering Extended" +
+ " Passive Mode (|||" + port + "|)");
+ } catch (IOException ssex) {
+ out.println("425 Can't build data connection:" +
+ " Connection refused.");
+ }
+ break;
+
case PASV:
if (!pasvEnabled) {
out.println("500 PASV is disabled, use PORT instead.");
@@ -467,6 +502,7 @@
}
}
public static void main(String[] args) throws Exception {
+ IPSupport.throwSkippedExceptionIfNonOperational();
FtpURL test = new FtpURL();
}
@@ -482,7 +518,7 @@
// Now let's check the URL handler
URL url = new URL("ftp://user:password@" + authority + "/%2Fetc/motd;type=a");
- URLConnection con = url.openConnection();
+ URLConnection con = url.openConnection(Proxy.NO_PROXY);
in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String s;
do {
@@ -507,7 +543,7 @@
// Now let's check the URL handler
url = new URL("ftp://user2@" + authority + "/%2Fusr/bin;type=d");
- con = url.openConnection();
+ con = url.openConnection(Proxy.NO_PROXY);
in = new BufferedReader(new InputStreamReader(con.getInputStream()));
do {
s = in.readLine();
@@ -523,9 +559,9 @@
// We're done!
} catch (Exception e) {
- throw new RuntimeException("FTP support error: " + e.getMessage());
+ throw new RuntimeException("FTP support error: " + e.getMessage(), e);
} finally {
- try { in.close(); } catch (IOException unused) {}
+ try { in.close(); } catch (Exception unused) {}
server.terminate();
server.server.close();
}
--- a/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java Wed May 15 19:09:54 2019 +0100
+++ b/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java Wed May 15 19:34:34 2019 +0100
@@ -34,6 +34,7 @@
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.URL;
+import java.net.Proxy;
public class FtpURLConnectionLeak {
@@ -48,7 +49,7 @@
try (server) {
for (int i = 0; i < 3; i++) {
try {
- InputStream stream = url.openStream();
+ InputStream stream = url.openConnection(Proxy.NO_PROXY).getInputStream();
} catch (FileNotFoundException expected) {
// should always reach this point since the path does not exist
System.out.println("caught expected " + expected);