8223880: Update sun/net/ftp/FtpURL.java and sun/net/ftp/FtpURLConnectionLeak.java to work with IPv6 addresses
authordfuchs
Wed, 15 May 2019 19:34:34 +0100
changeset 54886 4dd7ea5f28cf
parent 54885 e58e454c1409
child 54887 442e22c051f0
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
test/jdk/sun/net/ftp/FtpGetContent.java
test/jdk/sun/net/ftp/FtpURL.java
test/jdk/sun/net/ftp/FtpURLConnectionLeak.java
--- 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);