undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
157
test/jdk/java/net/Authenticator/AuthNPETest.java
Normal file
157
test/jdk/java/net/Authenticator/AuthNPETest.java
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4662246
|
||||
* @summary REGRESSION: plugin 14x client authentication dialog returns NullPointerException
|
||||
* @library /test/lib
|
||||
* @run main/othervm AuthNPETest
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true AuthNPETest
|
||||
*/
|
||||
|
||||
public class AuthNPETest {
|
||||
|
||||
static class BasicServer extends Thread {
|
||||
|
||||
ServerSocket server;
|
||||
|
||||
Socket s;
|
||||
InputStream is;
|
||||
OutputStream os;
|
||||
|
||||
static final String realm = "wallyworld";
|
||||
|
||||
String reply1 = "HTTP/1.1 401 Unauthorized\r\n"+
|
||||
"WWW-Authenticate: Basic realm=\""+realm+"\"\r\n\r\n";
|
||||
|
||||
String reply2 = "HTTP/1.1 200 OK\r\n"+
|
||||
"Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +
|
||||
"Server: Apache/1.3.14 (Unix)\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n" +
|
||||
"Content-Length: 10\r\n\r\n";
|
||||
|
||||
BasicServer(ServerSocket s) {
|
||||
server = s;
|
||||
}
|
||||
|
||||
void readAll(Socket s) throws IOException {
|
||||
byte[] buf = new byte [128];
|
||||
InputStream is = s.getInputStream();
|
||||
s.setSoTimeout(1000);
|
||||
try {
|
||||
while (is.read(buf) > 0) ;
|
||||
} catch (SocketTimeoutException x) { }
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
System.out.println("Server 1: accept");
|
||||
s = server.accept();
|
||||
System.out.println("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write(reply1.getBytes());
|
||||
readAll(s);
|
||||
s.close();
|
||||
|
||||
System.out.println("Server 2: accept");
|
||||
s = server.accept();
|
||||
System.out.println("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write((reply2+"HelloWorld").getBytes());
|
||||
readAll(s);
|
||||
s.close();
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println (e);
|
||||
}
|
||||
finished();
|
||||
}
|
||||
|
||||
public synchronized void finished() {
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
|
||||
MyAuthenticator() {
|
||||
super();
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication()
|
||||
{
|
||||
count++;
|
||||
System.out.println("Auth called");
|
||||
return (new PasswordAuthentication("user", "passwordNotCheckedAnyway".toCharArray()));
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void read(InputStream is) throws IOException {
|
||||
int c;
|
||||
System.out.println("reading");
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write(c);
|
||||
}
|
||||
System.out.println("");
|
||||
System.out.println("finished reading");
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
MyAuthenticator auth = new MyAuthenticator();
|
||||
Authenticator.setDefault(auth);
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
int port = ss.getLocalPort();
|
||||
BasicServer server = new BasicServer(ss);
|
||||
synchronized (server) {
|
||||
server.start();
|
||||
System.out.println ("client 1");
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(port)
|
||||
.toURL();
|
||||
URLConnection urlc = url.openConnection(Proxy.NO_PROXY);
|
||||
InputStream is = urlc.getInputStream();
|
||||
read(is);
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
213
test/jdk/java/net/Authenticator/B4678055.java
Normal file
213
test/jdk/java/net/Authenticator/B4678055.java
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4678055
|
||||
* @library /test/lib
|
||||
* @run main/othervm B4678055
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true B4678055
|
||||
* @summary Basic Authentication fails with multiple realms
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class B4678055 implements HttpHandler {
|
||||
|
||||
static volatile int count = 0;
|
||||
static volatile String authstring;
|
||||
|
||||
private void errorReply(HttpExchange req, String reply) throws IOException {
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().set("WWW-Authenticate", reply);
|
||||
req.sendResponseHeaders(401, -1);
|
||||
}
|
||||
|
||||
private void okReply (HttpExchange req) throws IOException {
|
||||
req.sendResponseHeaders(200, 0);
|
||||
try(PrintWriter pw = new PrintWriter(req.getResponseBody())) {
|
||||
pw.print("Hello .");
|
||||
}
|
||||
}
|
||||
|
||||
public void handle (HttpExchange req) {
|
||||
try {
|
||||
System.out.println("Server handling case: "+ count);
|
||||
if(req.getRequestHeaders().get("Authorization") != null) {
|
||||
authstring = req.getRequestHeaders().get("Authorization").get(0);
|
||||
System.out.println(authstring);
|
||||
}
|
||||
switch (count) {
|
||||
case 0:
|
||||
errorReply (req, "Basic realm=\"wallyworld\"");
|
||||
break;
|
||||
case 1:
|
||||
/* client stores a username/pw for wallyworld
|
||||
*/
|
||||
okReply (req);
|
||||
break;
|
||||
case 2:
|
||||
/* emulates a server that has configured a second
|
||||
* realm, but by misconfiguration uses the same
|
||||
* realm string as the previous one.
|
||||
*
|
||||
* An alternative (more likely) scenario that shows this behavior is
|
||||
* the case where the password in the original realm has changed
|
||||
*/
|
||||
errorReply (req, "Basic realm=\"wallyworld\"");
|
||||
break;
|
||||
case 3:
|
||||
/* The client replies with the username/password
|
||||
* from the first realm, which is wrong (unexpectedly)
|
||||
*/
|
||||
errorReply (req, "Basic realm=\"wallyworld\"");
|
||||
break;
|
||||
case 4:
|
||||
/* The client re-prompts for a password and
|
||||
* we now reply with an OK. The client with the bug
|
||||
* will throw NPE at this point.
|
||||
*/
|
||||
case 5:
|
||||
/* Repeat the OK, to make sure the same new auth string is sent */
|
||||
okReply (req);
|
||||
break;
|
||||
}
|
||||
count ++;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Unexpected exception for case " + count + ": " + e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static void read (InputStream is) throws IOException {
|
||||
int c;
|
||||
System.out.println ("reading");
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write (c);
|
||||
}
|
||||
System.out.println ("");
|
||||
System.out.println ("finished reading");
|
||||
}
|
||||
|
||||
static boolean checkFinalAuth () {
|
||||
return authstring.equals ("Basic dXNlcjpwYXNzMg==");
|
||||
}
|
||||
|
||||
static void client (String u) throws Exception {
|
||||
URL url = new URL (u);
|
||||
System.out.println ("client opening connection to: " + u);
|
||||
URLConnection urlc = url.openConnection ();
|
||||
InputStream is = urlc.getInputStream ();
|
||||
read (is);
|
||||
is.close();
|
||||
}
|
||||
|
||||
static HttpServer server;
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
B4678055 b4678055 = new B4678055();
|
||||
MyAuthenticator auth = new MyAuthenticator ();
|
||||
Authenticator.setDefault (auth);
|
||||
ProxySelector.setDefault(ProxySelector.of(null)); // no proxy
|
||||
try {
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
server = HttpServer.create(new InetSocketAddress(loopback, 0), 10);
|
||||
server.createContext("/", b4678055);
|
||||
server.setExecutor(Executors.newSingleThreadExecutor());
|
||||
server.start();
|
||||
String serverURL = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(server.getAddress().getPort())
|
||||
.path("/")
|
||||
.build()
|
||||
.toString();
|
||||
System.out.println("Server: listening at: " + serverURL);
|
||||
client(serverURL + "d1/foo.html");
|
||||
client(serverURL + "d2/foo.html");
|
||||
client(serverURL + "d2/foo.html");
|
||||
} catch (Exception e) {
|
||||
System.out.println("Client got exception: " + e);
|
||||
System.out.println("Terminating server");
|
||||
if (server != null) {
|
||||
server.stop(1);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
int f = auth.getCount();
|
||||
if (f != 2) {
|
||||
except ("Authenticator was called "+f+" times. Should be 2");
|
||||
}
|
||||
/* this checks the authorization string corresponding to second password "pass2"*/
|
||||
if (!checkFinalAuth()) {
|
||||
except ("Wrong authorization string received from client");
|
||||
}
|
||||
System.out.println("Terminating server");
|
||||
server.stop(1);
|
||||
}
|
||||
|
||||
public static void except (String s) {
|
||||
System.out.println("Check failed: " + s);
|
||||
System.out.println("Terminating server");
|
||||
server.stop(1);
|
||||
throw new RuntimeException (s);
|
||||
}
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
MyAuthenticator () {
|
||||
super ();
|
||||
}
|
||||
|
||||
volatile int count = 0;
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication () {
|
||||
PasswordAuthentication pw;
|
||||
if (count == 0) {
|
||||
pw = new PasswordAuthentication ("user", "pass1".toCharArray());
|
||||
} else {
|
||||
pw = new PasswordAuthentication ("user", "pass2".toCharArray());
|
||||
}
|
||||
count ++;
|
||||
return pw;
|
||||
}
|
||||
|
||||
public int getCount () {
|
||||
return (count);
|
||||
}
|
||||
}
|
||||
}
|
||||
198
test/jdk/java/net/Authenticator/B4722333.java
Normal file
198
test/jdk/java/net/Authenticator/B4722333.java
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4722333
|
||||
* @library /test/lib
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5 B4722333
|
||||
* @summary JRE Proxy Authentication Not Working with ISA2000
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class B4722333 implements HttpHandler {
|
||||
|
||||
static int count = 0;
|
||||
|
||||
static String[][] expected = {
|
||||
/* scheme realm/prompt */
|
||||
{"basic", "foo"},
|
||||
{"basic", "foobar"},
|
||||
{"digest", "biz"},
|
||||
{"digest", "bizbar"},
|
||||
{"digest", "foobiz"}
|
||||
};
|
||||
|
||||
public void handle(HttpExchange req) {
|
||||
try {
|
||||
if (count % 2 == 1) {
|
||||
req.sendResponseHeaders(200, 0);
|
||||
try(PrintWriter pw = new PrintWriter(req.getResponseBody())) {
|
||||
pw.print("Hello .");
|
||||
}
|
||||
} else {
|
||||
switch (count) {
|
||||
case 0:
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().set("WWW-Authenticate", "Basic realm=\"foo\"");
|
||||
req.getResponseHeaders().add("WWW-Authenticate", "Foo realm=\"bar\"");
|
||||
req.sendResponseHeaders(401, -1);
|
||||
break;
|
||||
case 2:
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().set("WWW-Authenticate", "Basic realm=\"foobar\" Foo realm=\"bar\"");
|
||||
req.sendResponseHeaders(401, -1);
|
||||
break;
|
||||
case 4:
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().set("WWW-Authenticate", "Digest realm=biz domain=/foo nonce=thisisanonce ");
|
||||
req.getResponseHeaders().add("WWW-Authenticate", "Basic realm=bizbar");
|
||||
req.sendResponseHeaders(401, -1);
|
||||
break;
|
||||
case 6:
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().set("WWW-Authenticate", "Digest realm=\"bizbar\" domain=/biz nonce=\"hereisanonce\" Basic realm=\"foobar\" Foo realm=\"bar\"");
|
||||
req.sendResponseHeaders(401, -1);
|
||||
break;
|
||||
case 8:
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().set("WWW-Authenticate", "Foo p1=1 p2=2 p3=3 p4=4 p5=5 p6=6 p7=7 p8=8 p9=10 Digest realm=foobiz domain=/foobiz nonce=newnonce");
|
||||
req.getResponseHeaders().add("WWW-Authenticate", "Basic realm=bizbar");
|
||||
req.sendResponseHeaders(401, -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
count ++;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static void read(InputStream is) throws IOException {
|
||||
int c;
|
||||
System.out.println("reading");
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write(c);
|
||||
}
|
||||
System.out.println("");
|
||||
System.out.println("finished reading");
|
||||
}
|
||||
|
||||
|
||||
static void client(String u) throws Exception {
|
||||
URL url = new URL (u);
|
||||
System.out.println("client opening connection to: " + u);
|
||||
URLConnection urlc = url.openConnection ();
|
||||
InputStream is = urlc.getInputStream ();
|
||||
read(is);
|
||||
is.close();
|
||||
}
|
||||
|
||||
static HttpServer server;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
B4722333 b4722333 = new B4722333();
|
||||
MyAuthenticator auth = new MyAuthenticator();
|
||||
Authenticator.setDefault(auth);
|
||||
try {
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
server = HttpServer.create(new InetSocketAddress(loopback, 0), 10);
|
||||
server.createContext("/", b4722333);
|
||||
server.setExecutor(Executors.newSingleThreadExecutor());
|
||||
server.start();
|
||||
System.out.println("Server started: listening on port: " + server.getAddress().getPort());
|
||||
String serverURL = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(server.getAddress().getPort())
|
||||
.path("/")
|
||||
.build()
|
||||
.toString();
|
||||
client(serverURL + "d1/d2/d3/foo.html");
|
||||
client(serverURL + "ASD/d3/x.html");
|
||||
client(serverURL + "biz/d3/x.html");
|
||||
client(serverURL + "bar/d3/x.html");
|
||||
client(serverURL + "fuzz/d3/x.html");
|
||||
} catch (Exception e) {
|
||||
if (server != null) {
|
||||
server.stop(1);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
int f = auth.getCount();
|
||||
if (f != expected.length) {
|
||||
except("Authenticator was called "+f+" times. Should be " + expected.length);
|
||||
}
|
||||
server.stop(1);
|
||||
}
|
||||
|
||||
public static void except(String s) {
|
||||
server.stop(1);
|
||||
throw new RuntimeException(s);
|
||||
}
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
MyAuthenticator() {
|
||||
super();
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication() {
|
||||
System.out.println("Auth called");
|
||||
String scheme = getRequestingScheme();
|
||||
System.out.println("getRequestingScheme() returns " + scheme);
|
||||
String prompt = getRequestingPrompt();
|
||||
System.out.println("getRequestingPrompt() returns " + prompt);
|
||||
|
||||
if (!scheme.equals(expected [count][0])) {
|
||||
B4722333.except("wrong scheme received, " + scheme + " expected " + expected [count][0]);
|
||||
}
|
||||
if (!prompt.equals(expected [count][1])) {
|
||||
B4722333.except("wrong realm received, " + prompt + " expected " + expected [count][1]);
|
||||
}
|
||||
count ++;
|
||||
return (new PasswordAuthentication("user", "passwordNotCheckedAnyway".toCharArray()));
|
||||
}
|
||||
|
||||
public int getCount () {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
169
test/jdk/java/net/Authenticator/B4759514.java
Normal file
169
test/jdk/java/net/Authenticator/B4759514.java
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4759514
|
||||
* @library /test/lib
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5 B4759514
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5 -Djava.net.preferIPv6Addresses=true B4759514
|
||||
* @summary Digest Authentication is erroniously quoting the nc value, contrary to RFC 2617
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class B4759514 implements HttpHandler {
|
||||
|
||||
static int count = 0;
|
||||
static String authstring;
|
||||
|
||||
void errorReply (HttpExchange req, String reply) throws IOException {
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().set("WWW-Authenticate", reply);
|
||||
req.sendResponseHeaders(401, -1);
|
||||
}
|
||||
|
||||
void okReply (HttpExchange req) throws IOException {
|
||||
req.sendResponseHeaders(200, 0);
|
||||
try(PrintWriter pw = new PrintWriter(req.getResponseBody())) {
|
||||
pw.print("Hello .");
|
||||
}
|
||||
}
|
||||
|
||||
public void handle (HttpExchange req) {
|
||||
try {
|
||||
if(req.getRequestHeaders().get("Authorization") != null) {
|
||||
authstring = req.getRequestHeaders().get("Authorization").get(0);
|
||||
System.out.println(authstring);
|
||||
}
|
||||
switch (count) {
|
||||
case 0:
|
||||
errorReply (req, "Digest realm=\"wallyworld\", nonce=\"1234\", domain=\"/\"");
|
||||
break;
|
||||
case 1:
|
||||
int n = authstring.indexOf ("nc=");
|
||||
if (n != -1) {
|
||||
if (authstring.charAt (n+3) == '\"') {
|
||||
req.sendResponseHeaders(400, -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
okReply (req);
|
||||
break;
|
||||
}
|
||||
count ++;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static void read (InputStream is) throws IOException {
|
||||
int c;
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write (c);
|
||||
}
|
||||
}
|
||||
|
||||
static void client (String u) throws Exception {
|
||||
URL url = new URL (u);
|
||||
System.out.println ("client opening connection to: " + u);
|
||||
URLConnection urlc = url.openConnection ();
|
||||
InputStream is = urlc.getInputStream ();
|
||||
read (is);
|
||||
is.close();
|
||||
}
|
||||
|
||||
static HttpServer server;
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
B4759514 b4759514 = new B4759514();
|
||||
MyAuthenticator auth = new MyAuthenticator ();
|
||||
Authenticator.setDefault (auth);
|
||||
ProxySelector.setDefault(ProxySelector.of(null)); // no proxy
|
||||
try {
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
server = HttpServer.create(new InetSocketAddress(loopback, 0), 10);
|
||||
server.createContext("/", b4759514);
|
||||
server.setExecutor(Executors.newSingleThreadExecutor());
|
||||
server.start();
|
||||
String serverURL = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(server.getAddress().getPort())
|
||||
.path("/")
|
||||
.build()
|
||||
.toString();
|
||||
System.out.println("Server: listening at: " + serverURL);
|
||||
client(serverURL + "d1/foo.html");
|
||||
} catch (Exception e) {
|
||||
if (server != null) {
|
||||
server.stop(1);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
int f = auth.getCount();
|
||||
if (f != 1) {
|
||||
except ("Authenticator was called "+f+" times. Should be 1");
|
||||
}
|
||||
server.stop(1);
|
||||
}
|
||||
|
||||
public static void except (String s) {
|
||||
server.stop(1);
|
||||
throw new RuntimeException (s);
|
||||
}
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
MyAuthenticator () {
|
||||
super ();
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication () {
|
||||
PasswordAuthentication pw;
|
||||
pw = new PasswordAuthentication ("user", "pass1".toCharArray());
|
||||
count ++;
|
||||
return pw;
|
||||
}
|
||||
|
||||
public int getCount () {
|
||||
return (count);
|
||||
}
|
||||
}
|
||||
}
|
||||
512
test/jdk/java/net/Authenticator/B4769350.java
Normal file
512
test/jdk/java/net/Authenticator/B4769350.java
Normal file
|
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2024, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4769350 8017779 8191169
|
||||
* @modules jdk.httpserver
|
||||
* @run main/othervm B4769350 server
|
||||
* @run main/othervm B4769350 proxy
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true B4769350 server
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true B4769350 proxy
|
||||
* @summary proxy authentication username and password caching only works in serial case
|
||||
* Run in othervm since the test sets system properties that are read by the
|
||||
* networking stack and cached when the HTTP handler is invoked, and previous
|
||||
* tests may already have invoked the HTTP handler.
|
||||
*/
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class B4769350 {
|
||||
|
||||
static int count = 0;
|
||||
static boolean error = false;
|
||||
|
||||
static void read (InputStream is) throws IOException {
|
||||
while (is.read() != -1) {
|
||||
//System.out.write (c);
|
||||
}
|
||||
}
|
||||
|
||||
static class Client extends Thread {
|
||||
String authority, path;
|
||||
boolean allowerror;
|
||||
|
||||
Client (String authority, String path, boolean allowerror) {
|
||||
super("Thread-" + path);
|
||||
this.authority = authority;
|
||||
this.path = path;
|
||||
this.allowerror = allowerror;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run () {
|
||||
try {
|
||||
URI u = new URI ("http", authority, path, null, null);
|
||||
URL url = u.toURL();
|
||||
URLConnection urlc = url.openConnection();
|
||||
try (InputStream is = urlc.getInputStream()) {
|
||||
read (is);
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
System.out.println (e);
|
||||
error = true;
|
||||
} catch (IOException e) {
|
||||
if (!allowerror) {
|
||||
System.out.println (Thread.currentThread().getName()
|
||||
+ " " + e);
|
||||
e.printStackTrace();
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Server implements AutoCloseable {
|
||||
HttpServer server;
|
||||
Executor executor;
|
||||
|
||||
public String getAddress() {
|
||||
return server.getAddress().getHostName();
|
||||
}
|
||||
|
||||
public void startServer() {
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
InetSocketAddress addr = new InetSocketAddress(loopback, 0);
|
||||
|
||||
try {
|
||||
server = HttpServer.create(addr, 0);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Server could not be created");
|
||||
}
|
||||
executor = Executors.newFixedThreadPool(10);
|
||||
server.setExecutor(executor);
|
||||
server.createContext("/test/realm1/t1a",
|
||||
new AuthenticationHandlerT1a() );
|
||||
server.createContext("/test/realm2/t1b",
|
||||
new AuthenticationHandlerT1b());
|
||||
server.createContext("/test/realm1/t1c",
|
||||
new AuthenticationHandlerT1c());
|
||||
server.createContext("/test/realm2/t1d",
|
||||
new AuthenticationHandlerT1d());
|
||||
server.createContext("/test/realm3/t2a",
|
||||
new AuthenticationHandlerT2a());
|
||||
server.createContext("/test/realm3/t2b",
|
||||
new AuthenticationHandlerT2b());
|
||||
server.createContext("/test/realm4/t3a",
|
||||
new AuthenticationHandlerT3a());
|
||||
server.createContext("/test/realm4/t3b",
|
||||
new AuthenticationHandlerT3bc());
|
||||
server.createContext("/test/realm4/t3c",
|
||||
new AuthenticationHandlerT3bc());
|
||||
t1Cond1 = new CyclicBarrier(3);
|
||||
server.start();
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return server.getAddress().getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (executor != null)
|
||||
((ExecutorService)executor).shutdownNow();
|
||||
if (server != null)
|
||||
server.stop(0);
|
||||
}
|
||||
|
||||
/* T1 tests the client by sending 4 requests to 2 different realms
|
||||
* in parallel. The client should recognise two pairs of dependent requests
|
||||
* and execute the first of each pair in parallel. When they both succeed
|
||||
* the second requests should be executed without calling the authenticator.
|
||||
* The test succeeds if the authenticator was only called twice.
|
||||
*/
|
||||
class AuthenticationHandlerT1a implements HttpHandler
|
||||
{
|
||||
volatile int count = -1;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
count++;
|
||||
try {
|
||||
switch(count) {
|
||||
case 0:
|
||||
AuthenticationHandler.errorReply(exchange,
|
||||
"Basic realm=\"realm1\"");
|
||||
break;
|
||||
case 1:
|
||||
t1Cond1.await();
|
||||
AuthenticationHandler.okReply(exchange);
|
||||
break;
|
||||
default:
|
||||
System.out.println ("Unexpected request");
|
||||
}
|
||||
} catch (InterruptedException |
|
||||
BrokenBarrierException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AuthenticationHandlerT1b implements HttpHandler
|
||||
{
|
||||
volatile int count = -1;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
count++;
|
||||
try {
|
||||
switch(count) {
|
||||
case 0:
|
||||
AuthenticationHandler.errorReply(exchange,
|
||||
"Basic realm=\"realm2\"");
|
||||
break;
|
||||
case 1:
|
||||
t1Cond1.await();
|
||||
AuthenticationHandler.okReply(exchange);
|
||||
break;
|
||||
default:
|
||||
System.out.println ("Unexpected request");
|
||||
}
|
||||
} catch (InterruptedException | BrokenBarrierException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AuthenticationHandlerT1c implements HttpHandler
|
||||
{
|
||||
volatile int count = -1;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
count++;
|
||||
switch(count) {
|
||||
case 0:
|
||||
AuthenticationHandler.errorReply(exchange,
|
||||
"Basic realm=\"realm1\"");
|
||||
break;
|
||||
case 1:
|
||||
AuthenticationHandler.okReply(exchange);
|
||||
break;
|
||||
default:
|
||||
System.out.println ("Unexpected request");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AuthenticationHandlerT1d implements HttpHandler
|
||||
{
|
||||
volatile int count = -1;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
count++;
|
||||
switch(count) {
|
||||
case 0:
|
||||
AuthenticationHandler.errorReply(exchange,
|
||||
"Basic realm=\"realm2\"");
|
||||
break;
|
||||
case 1:
|
||||
AuthenticationHandler.okReply(exchange);
|
||||
break;
|
||||
default:
|
||||
System.out.println ("Unexpected request");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* T2 tests to check that if initial authentication fails, the second will
|
||||
* succeed, and the authenticator is called twice
|
||||
*/
|
||||
|
||||
class AuthenticationHandlerT2a implements HttpHandler
|
||||
{
|
||||
volatile int count = -1;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
count++;
|
||||
if (count == 1) {
|
||||
t2condlatch.countDown();
|
||||
}
|
||||
AuthenticationHandler.errorReply(exchange,
|
||||
"Basic realm=\"realm3\"");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class AuthenticationHandlerT2b implements HttpHandler
|
||||
{
|
||||
volatile int count = -1;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
count++;
|
||||
switch(count) {
|
||||
case 0:
|
||||
AuthenticationHandler.errorReply(exchange,
|
||||
"Basic realm=\"realm3\"");
|
||||
break;
|
||||
case 1:
|
||||
AuthenticationHandler.okReply(exchange);
|
||||
break;
|
||||
default:
|
||||
System.out.println ("Unexpected request");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* T3 tests proxy and server authentication. three threads request same
|
||||
* resource at same time. Authenticator should be called once for server
|
||||
* and once for proxy
|
||||
*/
|
||||
|
||||
class AuthenticationHandlerT3a implements HttpHandler
|
||||
{
|
||||
volatile int count = -1;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
count++;
|
||||
switch(count) {
|
||||
case 0:
|
||||
AuthenticationHandler.proxyReply(exchange,
|
||||
"Basic realm=\"proxy\"");
|
||||
break;
|
||||
case 1:
|
||||
t3cond1.countDown();
|
||||
AuthenticationHandler.errorReply(exchange,
|
||||
"Basic realm=\"realm4\"");
|
||||
break;
|
||||
case 2:
|
||||
AuthenticationHandler.okReply(exchange);
|
||||
break;
|
||||
default:
|
||||
System.out.println ("Unexpected request");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AuthenticationHandlerT3bc implements HttpHandler
|
||||
{
|
||||
volatile int count = -1;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
count++;
|
||||
switch(count) {
|
||||
case 0:
|
||||
AuthenticationHandler.proxyReply(exchange,
|
||||
"Basic realm=\"proxy\"");
|
||||
break;
|
||||
case 1:
|
||||
AuthenticationHandler.okReply(exchange);
|
||||
break;
|
||||
default:
|
||||
System.out.println ("Unexpected request");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class AuthenticationHandler {
|
||||
static void errorReply(HttpExchange exchange, String reply)
|
||||
throws IOException
|
||||
{
|
||||
exchange.getResponseHeaders().add("Connection", "close");
|
||||
exchange.getResponseHeaders().add("WWW-Authenticate", reply);
|
||||
exchange.sendResponseHeaders(401, 0);
|
||||
exchange.close();
|
||||
}
|
||||
|
||||
static void proxyReply (HttpExchange exchange, String reply)
|
||||
throws IOException
|
||||
{
|
||||
exchange.getResponseHeaders().add("Proxy-Authenticate", reply);
|
||||
exchange.sendResponseHeaders(407, -1);
|
||||
}
|
||||
|
||||
static void okReply (HttpExchange exchange) throws IOException {
|
||||
exchange.getResponseHeaders().add("Connection", "close");
|
||||
String response = "Hello .";
|
||||
exchange.sendResponseHeaders(200, response.getBytes().length);
|
||||
try (OutputStream os = exchange.getResponseBody()) {
|
||||
os.write(response.getBytes());
|
||||
}
|
||||
exchange.close();
|
||||
}
|
||||
}
|
||||
|
||||
static Server server;
|
||||
static MyAuthenticator auth = new MyAuthenticator ();
|
||||
|
||||
static int redirects = 4;
|
||||
|
||||
static Client c1,c2,c3,c4,c5,c6,c7,c8,c9;
|
||||
|
||||
static CountDownLatch t2condlatch;
|
||||
static CountDownLatch t3cond1;
|
||||
static CyclicBarrier t1Cond1;
|
||||
|
||||
static void doServerTests (String authority, Server server) throws Exception
|
||||
{
|
||||
System.out.println ("Doing Server tests");
|
||||
System.out.println ("T1");
|
||||
c1 = new Client (authority, "/test/realm1/t1a", false);
|
||||
c2 = new Client (authority, "/test/realm2/t1b", false);
|
||||
c3 = new Client (authority, "/test/realm1/t1c", false);
|
||||
c4 = new Client (authority, "/test/realm2/t1d", false);
|
||||
c1.start(); c2.start();
|
||||
t1Cond1.await();
|
||||
c3.start(); c4.start();
|
||||
c1.join(); c2.join(); c3.join(); c4.join();
|
||||
|
||||
int f = auth.getCount();
|
||||
if (f != 2) {
|
||||
except ("Authenticator was called "+f+" times. Should be 2",
|
||||
server);
|
||||
}
|
||||
if (error) {
|
||||
except ("error occurred", server);
|
||||
}
|
||||
|
||||
auth.resetCount();
|
||||
System.out.println ("T2");
|
||||
|
||||
c5 = new Client (authority, "/test/realm3/t2a", true);
|
||||
c6 = new Client (authority, "/test/realm3/t2b", false);
|
||||
t2condlatch = new CountDownLatch(1);
|
||||
c5.start ();
|
||||
t2condlatch.await();
|
||||
c6.start ();
|
||||
c5.join(); c6.join();
|
||||
|
||||
f = auth.getCount();
|
||||
if (f != redirects+1) {
|
||||
except ("Authenticator was called "+f+" times. Should be: "
|
||||
+ redirects+1, server);
|
||||
}
|
||||
if (error) {
|
||||
except ("error occurred", server);
|
||||
}
|
||||
}
|
||||
|
||||
static void doProxyTests (String authority, Server server) throws Exception
|
||||
{
|
||||
System.out.println ("Doing Proxy tests");
|
||||
c7 = new Client (authority, "/test/realm4/t3a", false);
|
||||
c8 = new Client (authority, "/test/realm4/t3b", false);
|
||||
c9 = new Client (authority, "/test/realm4/t3c", false);
|
||||
t3cond1 = new CountDownLatch(1);
|
||||
c7.start ();
|
||||
t3cond1.await();
|
||||
c8.start ();
|
||||
c9.start ();
|
||||
c7.join(); c8.join(); c9.join();
|
||||
|
||||
int f = auth.getCount();
|
||||
if (f != 2) {
|
||||
except ("Authenticator was called "+f+" times. Should be: " + 2,
|
||||
server);
|
||||
}
|
||||
if (error) {
|
||||
except ("error occurred", server);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
new B4769350().runTest(args[0].equals ("proxy"));
|
||||
}
|
||||
|
||||
public void runTest(boolean proxy) throws Exception {
|
||||
System.setProperty ("http.maxRedirects", Integer.toString (redirects));
|
||||
System.setProperty ("http.auth.serializeRequests", "true");
|
||||
Authenticator.setDefault (auth);
|
||||
try (Server server = new Server()) {
|
||||
server.startServer();
|
||||
System.out.println ("Server: listening on port: "
|
||||
+ server.getPort());
|
||||
if (proxy) {
|
||||
System.setProperty ("http.proxyHost",
|
||||
InetAddress.getLoopbackAddress().getHostAddress());
|
||||
System.setProperty ("http.proxyPort",
|
||||
Integer.toString(server.getPort()));
|
||||
doProxyTests ("www.foo.com", server);
|
||||
} else {
|
||||
ProxySelector.setDefault(ProxySelector.of(null));
|
||||
doServerTests (authority(server.getPort()), server);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static String authority(int port) {
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
String hoststr = loopback.getHostAddress();
|
||||
if (hoststr.indexOf(':') > -1) {
|
||||
hoststr = "[" + hoststr + "]";
|
||||
}
|
||||
return hoststr + ":" + port;
|
||||
}
|
||||
|
||||
public static void except (String s, Server server) {
|
||||
server.close();
|
||||
throw new RuntimeException (s);
|
||||
}
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
MyAuthenticator () {
|
||||
super ();
|
||||
}
|
||||
|
||||
volatile int count = 0;
|
||||
|
||||
@Override
|
||||
public PasswordAuthentication getPasswordAuthentication () {
|
||||
PasswordAuthentication pw;
|
||||
pw = new PasswordAuthentication ("user", "pass1".toCharArray());
|
||||
count ++;
|
||||
return pw;
|
||||
}
|
||||
|
||||
public void resetCount () {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
public int getCount () {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
146
test/jdk/java/net/Authenticator/B4921848.java
Normal file
146
test/jdk/java/net/Authenticator/B4921848.java
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4921848
|
||||
* @library /test/lib
|
||||
* @run main/othervm -Dhttp.auth.preference=basic B4921848
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true
|
||||
* -Dhttp.auth.preference=basic B4921848
|
||||
* @summary Allow user control over authentication schemes
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class B4921848 implements HttpHandler {
|
||||
|
||||
static int count = 0;
|
||||
|
||||
public void handle (HttpExchange req) {
|
||||
try {
|
||||
if (count == 0 ) {
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().add("WWW-Authenticate", "Basic realm=\"foo\"");
|
||||
req.getResponseHeaders().add("WWW-Authenticate", "Digest realm=\"bar\" domain=/biz nonce=\"hereisanonce\"");
|
||||
req.sendResponseHeaders(401, -1);
|
||||
} else {
|
||||
String authheader = req.getRequestHeaders().get("Authorization").get(0);
|
||||
if (authheader.startsWith ("Basic")) {
|
||||
req.sendResponseHeaders(200, 0);
|
||||
try(PrintWriter pw = new PrintWriter(req.getResponseBody())) {
|
||||
pw.print("Hello .");
|
||||
}
|
||||
} else {
|
||||
req.sendResponseHeaders(400, -1);
|
||||
}
|
||||
}
|
||||
count ++;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static void read (InputStream is) throws IOException {
|
||||
int c;
|
||||
System.out.println ("reading");
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write (c);
|
||||
}
|
||||
System.out.println ("");
|
||||
System.out.println ("finished reading");
|
||||
}
|
||||
|
||||
|
||||
static void client (String u) throws Exception {
|
||||
URL url = new URL (u);
|
||||
System.out.println ("client opening connection to: " + u);
|
||||
URLConnection urlc = url.openConnection ();
|
||||
InputStream is = urlc.getInputStream ();
|
||||
read (is);
|
||||
is.close();
|
||||
}
|
||||
|
||||
static HttpServer server;
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
B4921848 b4921848 = new B4921848();
|
||||
MyAuthenticator auth = new MyAuthenticator ();
|
||||
Authenticator.setDefault (auth);
|
||||
ProxySelector.setDefault(ProxySelector.of(null)); // no proxy
|
||||
try {
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
server = HttpServer.create(new InetSocketAddress(loopback, 0), 10);
|
||||
server.createContext("/", b4921848);
|
||||
server.setExecutor(Executors.newSingleThreadExecutor());
|
||||
server.start();
|
||||
String serverURL = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(server.getAddress().getPort())
|
||||
.path("/")
|
||||
.build()
|
||||
.toString();
|
||||
System.out.println("Server: listening at: " + serverURL);
|
||||
client(serverURL + "d1/d2/d3/foo.html");
|
||||
} catch (Exception e) {
|
||||
if (server != null) {
|
||||
server.stop(1);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
server.stop(1);
|
||||
}
|
||||
|
||||
public static void except (String s) {
|
||||
server.stop(1);
|
||||
throw new RuntimeException (s);
|
||||
}
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
MyAuthenticator () {
|
||||
super ();
|
||||
}
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication () {
|
||||
return (new PasswordAuthentication ("user", "passwordNotCheckedAnyway".toCharArray()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
168
test/jdk/java/net/Authenticator/B4962064.java
Normal file
168
test/jdk/java/net/Authenticator/B4962064.java
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2004, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4962064
|
||||
* @run main/othervm B4962064
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true B4962064
|
||||
* @summary Extend Authenticator to provide access to request URI and server/proxy
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
public class B4962064 implements HttpHandler {
|
||||
|
||||
static int count = 0;
|
||||
|
||||
public void handle (HttpExchange req) {
|
||||
try {
|
||||
switch (count) {
|
||||
case 0:
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().add("WWW-Authenticate", "Basic realm=\"foo\"");
|
||||
req.sendResponseHeaders(401, -1);
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
req.sendResponseHeaders(200, 0);
|
||||
try(PrintWriter pw = new PrintWriter(req.getResponseBody())) {
|
||||
pw.print("Hello .");
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
req.getResponseHeaders().set("Connection", "close");
|
||||
req.getResponseHeaders().add("Proxy-Authenticate", "Basic realm=\"foo\"");
|
||||
req.sendResponseHeaders(407, -1);
|
||||
break;
|
||||
}
|
||||
count ++;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static void read (InputStream is) throws IOException {
|
||||
int c;
|
||||
System.out.println ("reading");
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write (c);
|
||||
}
|
||||
System.out.println ("");
|
||||
System.out.println ("finished reading");
|
||||
}
|
||||
|
||||
|
||||
static void client (String u) throws Exception {
|
||||
URL url = new URL (u);
|
||||
System.out.println ("client opening connection to: " + u);
|
||||
URLConnection urlc = url.openConnection ();
|
||||
InputStream is = urlc.getInputStream ();
|
||||
read (is);
|
||||
is.close();
|
||||
}
|
||||
|
||||
static HttpServer server;
|
||||
static URL urlsave;
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
B4962064 b4962064 = new B4962064();
|
||||
try {
|
||||
InetAddress address = InetAddress.getLoopbackAddress();
|
||||
InetAddress resolved = InetAddress.getByName(address.getHostName());
|
||||
System.out.println("Lookup: " + address + " -> \""
|
||||
+ address.getHostName() + "\" -> "
|
||||
+ resolved);
|
||||
server = HttpServer.create(new InetSocketAddress(address, 0), 10);
|
||||
server.createContext("/", b4962064);
|
||||
server.setExecutor(Executors.newSingleThreadExecutor());
|
||||
server.start();
|
||||
int port = server.getAddress().getPort();
|
||||
String proxyHost = address.equals(resolved)
|
||||
? address.getHostName()
|
||||
: address.getHostAddress();
|
||||
System.setProperty ("http.proxyHost", proxyHost);
|
||||
System.setProperty ("http.proxyPort", Integer.toString (port));
|
||||
MyAuthenticator auth = new MyAuthenticator ();
|
||||
Authenticator.setDefault (auth);
|
||||
System.out.println ("Server started: listening on port: " + port);
|
||||
String s = new String ("http://foo.com/d1/d2/d3/foo.html");
|
||||
urlsave = new URL (s);
|
||||
client (s);
|
||||
s = new String ("http://bar.com/dr/d3/foo.html");
|
||||
urlsave = new URL (s);
|
||||
client (s);
|
||||
} catch (Exception e) {
|
||||
if (server != null) {
|
||||
server.stop(1);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
server.stop(1);
|
||||
}
|
||||
|
||||
public static void except (String s) {
|
||||
server.stop(1);
|
||||
throw new RuntimeException (s);
|
||||
}
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
int count = 0;
|
||||
MyAuthenticator () {
|
||||
super ();
|
||||
}
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication () {
|
||||
URL url = getRequestingURL ();
|
||||
if (!url.equals (urlsave)) {
|
||||
except ("urls not equal");
|
||||
}
|
||||
Authenticator.RequestorType expected;
|
||||
if (count == 0) {
|
||||
expected = Authenticator.RequestorType.SERVER;
|
||||
} else {
|
||||
expected = Authenticator.RequestorType.PROXY;
|
||||
}
|
||||
if (getRequestorType() != expected) {
|
||||
except ("wrong authtype");
|
||||
}
|
||||
count ++;
|
||||
return (new PasswordAuthentication ("user", "passwordNotCheckedAnyway".toCharArray()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
277
test/jdk/java/net/Authenticator/B6870935.java
Normal file
277
test/jdk/java/net/Authenticator/B6870935.java
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2022, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6870935
|
||||
* @library /test/lib
|
||||
* @modules java.base/sun.net.www
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5
|
||||
* -Dhttp.nonProxyHosts="" -Dhttp.auth.digest.validateProxy=true B6870935
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5
|
||||
* -Djava.net.preferIPv6Addresses=true
|
||||
* -Dhttp.nonProxyHosts="" -Dhttp.auth.digest.validateProxy=true B6870935
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.net.*;
|
||||
import java.security.*;
|
||||
|
||||
import jdk.test.lib.net.HttpHeaderParser;
|
||||
import sun.net.www.*;
|
||||
|
||||
/* This is one simple test of the RFC2617 digest authentication behavior
|
||||
* It specifically tests that the client correctly checks the returned
|
||||
* Authentication-Info header field from the server and throws an exception
|
||||
* if the password is wrong
|
||||
*/
|
||||
|
||||
public class B6870935 {
|
||||
|
||||
static char[] passwd = "password".toCharArray();
|
||||
static String username = "user";
|
||||
static String nonce = "abcdefghijklmnopqrstuvwxyz";
|
||||
static String realm = "wallyworld";
|
||||
static String uri = "http://www.ibm.com";
|
||||
static volatile boolean error = false;
|
||||
|
||||
static class DigestServer extends Thread {
|
||||
|
||||
ServerSocket s;
|
||||
InputStream is;
|
||||
OutputStream os;
|
||||
int port;
|
||||
|
||||
String reply1 = "HTTP/1.1 407 Proxy Authentication Required\r\n"+
|
||||
"Proxy-Authenticate: Digest realm=\""+realm+"\" domain=/ "+
|
||||
"nonce=\""+nonce+"\" qop=\"auth\"\r\n\r\n";
|
||||
|
||||
String reply2 = "HTTP/1.1 200 OK\r\n" +
|
||||
"Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +
|
||||
"Server: Apache/1.3.14 (Unix)\r\n" +
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n" +
|
||||
"Transfer-encoding: chunked\r\n\r\n"+
|
||||
"B\r\nHelloWorld1\r\n"+
|
||||
"B\r\nHelloWorld2\r\n"+
|
||||
"B\r\nHelloWorld3\r\n"+
|
||||
"B\r\nHelloWorld4\r\n"+
|
||||
"B\r\nHelloWorld5\r\n"+
|
||||
"0\r\n"+
|
||||
"Proxy-Authentication-Info: ";
|
||||
|
||||
DigestServer (ServerSocket y) {
|
||||
s = y;
|
||||
port = s.getLocalPort();
|
||||
}
|
||||
|
||||
public void run () {
|
||||
try {
|
||||
System.out.println("Server started");
|
||||
Socket s1 = s.accept ();
|
||||
is = s1.getInputStream ();
|
||||
os = s1.getOutputStream ();
|
||||
is.read ();
|
||||
os.write (reply1.getBytes());
|
||||
System.out.println("First response sent");
|
||||
Thread.sleep (2000);
|
||||
s1.close ();
|
||||
System.out.println("First connection closed");
|
||||
|
||||
s1 = s.accept ();
|
||||
is = s1.getInputStream ();
|
||||
os = s1.getOutputStream ();
|
||||
// is.read ();
|
||||
// need to get the cnonce out of the response
|
||||
HttpHeaderParser header = new HttpHeaderParser (is);
|
||||
String raw = header.getHeaderValue("Proxy-Authorization") != null ?
|
||||
header.getHeaderValue("Proxy-Authorization").get(0) : null;
|
||||
HeaderParser parser = new HeaderParser (raw);
|
||||
String cnonce = parser.findValue ("cnonce");
|
||||
String cnstring = parser.findValue ("nc");
|
||||
String clientrsp = parser.findValue ("response");
|
||||
String expected = computeDigest(
|
||||
true, username,passwd,realm,
|
||||
"GET", uri, nonce, cnonce, cnstring
|
||||
);
|
||||
if (!expected.equals(clientrsp)) {
|
||||
s1.close ();
|
||||
s.close ();
|
||||
error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
String reply = reply2 + getAuthorization (
|
||||
realm, false, uri, "GET", cnonce,
|
||||
cnstring, passwd, username
|
||||
) +"\r\n";
|
||||
os.write (reply.getBytes());
|
||||
System.out.println("Second response sent");
|
||||
Thread.sleep (2000);
|
||||
s1.close ();
|
||||
System.out.println("Second connection closed");
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println (e);
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
System.out.println("Server finished");
|
||||
}
|
||||
}
|
||||
|
||||
private String getAuthorization (String realm, boolean isRequest, String uri, String method, String cnonce, String cnstring, char[] password, String username) {
|
||||
String response;
|
||||
|
||||
try {
|
||||
response = computeDigest(isRequest, username,passwd,realm,
|
||||
method, uri, nonce, cnonce, cnstring);
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String value = "Digest"
|
||||
+ " qop=\"auth"
|
||||
+ "\", cnonce=\"" + cnonce
|
||||
+ "\", rspauth=\"" + response
|
||||
+ "\", nc=\"" + cnstring + "\"";
|
||||
return (value+ "\r\n");
|
||||
}
|
||||
|
||||
private String computeDigest(
|
||||
boolean isRequest, String userName, char[] password,
|
||||
String realm, String connMethod,
|
||||
String requestURI, String nonceString,
|
||||
String cnonce, String ncValue
|
||||
) throws NoSuchAlgorithmException
|
||||
{
|
||||
|
||||
String A1, HashA1;
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
|
||||
{
|
||||
A1 = userName + ":" + realm + ":";
|
||||
HashA1 = encode(A1, password, md);
|
||||
}
|
||||
|
||||
String A2;
|
||||
if (isRequest) {
|
||||
A2 = connMethod + ":" + requestURI;
|
||||
} else {
|
||||
A2 = ":" + requestURI;
|
||||
}
|
||||
String HashA2 = encode(A2, null, md);
|
||||
String combo, finalHash;
|
||||
|
||||
{ /* RRC2617 when qop=auth */
|
||||
combo = HashA1+ ":" + nonceString + ":" + ncValue + ":" +
|
||||
cnonce + ":auth:" +HashA2;
|
||||
|
||||
}
|
||||
finalHash = encode(combo, null, md);
|
||||
return finalHash;
|
||||
}
|
||||
|
||||
private String encode(String src, char[] passwd, MessageDigest md) {
|
||||
md.update(src.getBytes());
|
||||
if (passwd != null) {
|
||||
byte[] passwdBytes = new byte[passwd.length];
|
||||
for (int i=0; i<passwd.length; i++)
|
||||
passwdBytes[i] = (byte)passwd[i];
|
||||
md.update(passwdBytes);
|
||||
Arrays.fill(passwdBytes, (byte)0x00);
|
||||
}
|
||||
byte[] digest = md.digest();
|
||||
return HexFormat.of().formatHex(digest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
public MyAuthenticator () {
|
||||
super ();
|
||||
}
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication ()
|
||||
{
|
||||
return (new PasswordAuthentication (username, passwd));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int nLoops = 1;
|
||||
int nSize = 10;
|
||||
int port, n =0;
|
||||
byte b[] = new byte[nSize];
|
||||
DigestServer server;
|
||||
ServerSocket sock;
|
||||
|
||||
InetAddress address = InetAddress.getLoopbackAddress();
|
||||
InetAddress resolved = InetAddress.getByName(address.getHostName());
|
||||
System.out.println("Lookup: "
|
||||
+ address + " -> \"" + address.getHostName() + "\" -> "
|
||||
+ resolved);
|
||||
String proxyHost = address.equals(resolved)
|
||||
? address.getHostName()
|
||||
: address.getHostAddress();
|
||||
try {
|
||||
sock = new ServerSocket();
|
||||
sock.bind(new InetSocketAddress(address, 0));
|
||||
port = sock.getLocalPort ();
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println ("Exception: " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
server = new DigestServer(sock);
|
||||
server.start ();
|
||||
|
||||
try {
|
||||
Authenticator.setDefault (new MyAuthenticator ());
|
||||
SocketAddress addr = InetSocketAddress.createUnresolved(proxyHost, port);
|
||||
Proxy proxy = new Proxy (Proxy.Type.HTTP, addr);
|
||||
String s = "http://www.ibm.com";
|
||||
URL url = new URL(s);
|
||||
System.out.println("opening connection through proxy: " + addr);
|
||||
java.net.URLConnection conURL = url.openConnection(proxy);
|
||||
|
||||
InputStream in = conURL.getInputStream();
|
||||
int c;
|
||||
while ((c = in.read ()) != -1) {
|
||||
}
|
||||
in.close ();
|
||||
}
|
||||
catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
error = true;
|
||||
sock.close();
|
||||
} finally {
|
||||
server.join();
|
||||
}
|
||||
if (error) {
|
||||
throw new RuntimeException ("Error in test");
|
||||
}
|
||||
}
|
||||
}
|
||||
204
test/jdk/java/net/Authenticator/B8034170.java
Normal file
204
test/jdk/java/net/Authenticator/B8034170.java
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8034170
|
||||
* @summary Digest authentication interop issue
|
||||
* @library /test/lib
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5 B8034170 unquoted
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5
|
||||
* -Dhttp.auth.digest.quoteParameters=true B8034170 quoted
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5
|
||||
* -Djava.net.preferIPv6Addresses=true B8034170 unquoted
|
||||
*/
|
||||
|
||||
public class B8034170 {
|
||||
|
||||
static boolean expectQuotes;
|
||||
|
||||
static class BasicServer extends Thread {
|
||||
|
||||
ServerSocket server;
|
||||
|
||||
Socket s;
|
||||
InputStream is;
|
||||
OutputStream os;
|
||||
|
||||
static final String realm = "wallyworld";
|
||||
|
||||
String reply1 = "HTTP/1.1 401 Unauthorized\r\n"+
|
||||
"WWW-Authenticate: Digest realm=\""+realm+"\", qop=\"auth\"" +
|
||||
", nonce=\"8989de95ea2402b64d73cecdb15da255\"" +
|
||||
", opaque=\"bbfb4c9ee92ddccc73521c3e6e841ba2\"\r\n\r\n";
|
||||
|
||||
String OKreply = "HTTP/1.1 200 OK\r\n"+
|
||||
"Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +
|
||||
"Server: Apache/1.3.14 (Unix)\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Type: text/plain; charset=iso-8859-1\r\n" +
|
||||
"Content-Length: 10\r\n\r\n";
|
||||
|
||||
String ERRreply = "HTTP/1.1 500 Internal server error\r\n"+
|
||||
"Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +
|
||||
"Server: Apache/1.3.14 (Unix)\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: 0\r\n\r\n";
|
||||
|
||||
BasicServer (ServerSocket s) {
|
||||
server = s;
|
||||
}
|
||||
|
||||
int readAll (Socket s, byte[] buf) throws IOException {
|
||||
int pos = 0;
|
||||
InputStream is = s.getInputStream ();
|
||||
// wait two seconds for request, as client doesn't close
|
||||
// the connection
|
||||
s.setSoTimeout(2000);
|
||||
try {
|
||||
int n;
|
||||
while ((n=is.read(buf, pos, buf.length-pos)) > 0)
|
||||
pos +=n;
|
||||
} catch (SocketTimeoutException x) { }
|
||||
return pos;
|
||||
}
|
||||
|
||||
public void run () {
|
||||
byte[] buf = new byte[5000];
|
||||
try {
|
||||
System.out.println ("Server 1: accept");
|
||||
s = server.accept ();
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write (reply1.getBytes());
|
||||
readAll (s, buf);
|
||||
s.close ();
|
||||
|
||||
System.out.println ("Server 2: accept");
|
||||
s = server.accept ();
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
int count = readAll (s, buf);
|
||||
String reply = new String(buf, 0, count);
|
||||
|
||||
boolean error;
|
||||
|
||||
if (expectQuotes) {
|
||||
error = false;
|
||||
if (!reply.contains("qop=\"auth\"")) {
|
||||
System.out.println ("Expecting quoted qop. Not found");
|
||||
error = true;
|
||||
}
|
||||
if (!reply.contains("algorithm=\"MD5\"")) {
|
||||
System.out.println ("Expecting quoted algorithm. Not found");
|
||||
error = true;
|
||||
}
|
||||
} else {
|
||||
error = false;
|
||||
if (!reply.contains("qop=auth")) {
|
||||
System.out.println ("Expecting unquoted qop. Not found");
|
||||
error = true;
|
||||
}
|
||||
if (!reply.contains("algorithm=MD5")) {
|
||||
System.out.println ("Expecting unquoted algorithm. Not found");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
os.write(ERRreply.getBytes());
|
||||
os.flush();
|
||||
s.close();
|
||||
} else {
|
||||
os.write((OKreply+"HelloWorld").getBytes());
|
||||
os.flush();
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println (e);
|
||||
}
|
||||
finished ();
|
||||
}
|
||||
|
||||
public synchronized void finished () {
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyAuthenticator3 extends Authenticator {
|
||||
PasswordAuthentication pw;
|
||||
MyAuthenticator3 () {
|
||||
super ();
|
||||
pw = new PasswordAuthentication ("user", "passwordNotCheckedAnyway".toCharArray());
|
||||
}
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication ()
|
||||
{
|
||||
System.out.println ("Auth called");
|
||||
return pw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void read (InputStream is) throws IOException {
|
||||
int c;
|
||||
System.out.println ("reading");
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write (c);
|
||||
}
|
||||
System.out.println ("");
|
||||
System.out.println ("finished reading");
|
||||
}
|
||||
|
||||
public static void main (String args[]) throws Exception {
|
||||
expectQuotes = args[0].equals("quoted");
|
||||
|
||||
MyAuthenticator3 auth = new MyAuthenticator3 ();
|
||||
Authenticator.setDefault (auth);
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
int port = ss.getLocalPort ();
|
||||
BasicServer server = new BasicServer (ss);
|
||||
synchronized (server) {
|
||||
server.start();
|
||||
System.out.println ("client 1");
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(port)
|
||||
.path("/d1/d2/d3/foo.html")
|
||||
.toURL();
|
||||
URLConnection urlc = url.openConnection(Proxy.NO_PROXY);
|
||||
InputStream is = urlc.getInputStream ();
|
||||
read (is);
|
||||
is.close ();
|
||||
}
|
||||
}
|
||||
}
|
||||
190
test/jdk/java/net/Authenticator/BasicTest.java
Normal file
190
test/jdk/java/net/Authenticator/BasicTest.java
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4474947
|
||||
* @summary fix for bug #4244472 is incomplete - HTTP authorization still needs work
|
||||
* @library /test/lib
|
||||
* @run main/othervm BasicTest
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true BasicTest
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note, this is not a general purpose test for Basic Authentication because
|
||||
* it does not check the correctness of the data, only whether the user
|
||||
* authenticator gets called once as expected
|
||||
*/
|
||||
|
||||
public class BasicTest {
|
||||
|
||||
static class BasicServer extends Thread {
|
||||
|
||||
ServerSocket server;
|
||||
|
||||
Socket s;
|
||||
InputStream is;
|
||||
OutputStream os;
|
||||
|
||||
static final String realm = "wallyworld";
|
||||
|
||||
String reply1 = "HTTP/1.1 401 Unauthorized\r\n"+
|
||||
"WWW-Authenticate: Basic realm=\""+realm+"\"\r\n\r\n";
|
||||
|
||||
String reply2 = "HTTP/1.1 200 OK\r\n"+
|
||||
"Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +
|
||||
"Server: Apache/1.3.14 (Unix)\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n" +
|
||||
"Content-Length: 10\r\n\r\n";
|
||||
|
||||
BasicServer (ServerSocket s) {
|
||||
server = s;
|
||||
}
|
||||
|
||||
void readAll (Socket s) throws IOException {
|
||||
byte[] buf = new byte [128];
|
||||
InputStream is = s.getInputStream ();
|
||||
while (is.available() > 0) {
|
||||
is.read (buf);
|
||||
}
|
||||
}
|
||||
|
||||
public void run () {
|
||||
try {
|
||||
System.out.println ("Server 1: accept");
|
||||
s = server.accept ();
|
||||
readAll (s);
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write (reply1.getBytes());
|
||||
Thread.sleep (500);
|
||||
|
||||
System.out.println ("Server 2: accept");
|
||||
s = server.accept ();
|
||||
readAll (s);
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write ((reply2+"HelloWorld").getBytes());
|
||||
|
||||
/* Second request now */
|
||||
|
||||
System.out.println ("Server 3: accept");
|
||||
s = server.accept ();
|
||||
readAll (s);
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write (reply1.getBytes());
|
||||
Thread.sleep (500);
|
||||
s.close ();
|
||||
|
||||
System.out.println ("Server 4: accept");
|
||||
s = server.accept ();
|
||||
readAll (s);
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write ((reply2+"HelloAgain").getBytes());
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println (e);
|
||||
}
|
||||
finished ();
|
||||
}
|
||||
|
||||
public synchronized void finished () {
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
MyAuthenticator () {
|
||||
super ();
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication ()
|
||||
{
|
||||
count ++;
|
||||
System.out.println ("Auth called");
|
||||
return (new PasswordAuthentication ("user", "passwordNotCheckedAnyway".toCharArray()));
|
||||
}
|
||||
|
||||
public int getCount () {
|
||||
return (count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void read (InputStream is) throws IOException {
|
||||
int c;
|
||||
System.out.println ("reading");
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write (c);
|
||||
}
|
||||
System.out.println ("");
|
||||
System.out.println ("finished reading");
|
||||
}
|
||||
|
||||
public static void main (String args[]) throws Exception {
|
||||
MyAuthenticator auth = new MyAuthenticator ();
|
||||
Authenticator.setDefault (auth);
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
int port = ss.getLocalPort ();
|
||||
BasicServer server = new BasicServer (ss);
|
||||
synchronized (server) {
|
||||
server.start();
|
||||
System.out.println ("client 1");
|
||||
String base = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(port)
|
||||
.path("/")
|
||||
.build()
|
||||
.toString();
|
||||
URL url = new URL(base + "d1/d2/d3/foo.html");
|
||||
URLConnection urlc = url.openConnection(Proxy.NO_PROXY);
|
||||
InputStream is = urlc.getInputStream ();
|
||||
read (is);
|
||||
System.out.println ("client 2");
|
||||
url = new URL(base + "d1/foo.html");
|
||||
urlc = url.openConnection(Proxy.NO_PROXY);
|
||||
is = urlc.getInputStream ();
|
||||
read (is);
|
||||
server.wait ();
|
||||
// check if authenticator was called once (ok) or twice (not)
|
||||
int f = auth.getCount();
|
||||
if (f != 1) {
|
||||
throw new RuntimeException ("Authenticator was called "+f+" times. Should be 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
158
test/jdk/java/net/Authenticator/BasicTest3.java
Normal file
158
test/jdk/java/net/Authenticator/BasicTest3.java
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4513440
|
||||
* @summary BasicAuthentication is zeroing out the given password
|
||||
* @library /test/lib
|
||||
* @run main/othervm BasicTest3
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true BasicTest3
|
||||
*/
|
||||
|
||||
public class BasicTest3 {
|
||||
|
||||
static class BasicServer3 extends Thread {
|
||||
|
||||
ServerSocket server;
|
||||
|
||||
Socket s;
|
||||
InputStream is;
|
||||
OutputStream os;
|
||||
|
||||
static final String realm = "wallyworld";
|
||||
|
||||
String reply1 = "HTTP/1.1 401 Unauthorized\r\n"+
|
||||
"WWW-Authenticate: Basic realm=\""+realm+"\"\r\n\r\n";
|
||||
|
||||
String reply2 = "HTTP/1.1 200 OK\r\n"+
|
||||
"Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +
|
||||
"Server: Apache/1.3.14 (Unix)\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n" +
|
||||
"Content-Length: 10\r\n\r\n";
|
||||
|
||||
BasicServer3 (ServerSocket s) {
|
||||
server = s;
|
||||
}
|
||||
|
||||
void readAll (Socket s) throws IOException {
|
||||
byte[] buf = new byte [128];
|
||||
InputStream is = s.getInputStream ();
|
||||
s.setSoTimeout(1000);
|
||||
try {
|
||||
while (is.read(buf) > 0) ;
|
||||
} catch (SocketTimeoutException x) { }
|
||||
}
|
||||
|
||||
public void run () {
|
||||
try {
|
||||
System.out.println ("Server 1: accept");
|
||||
s = server.accept ();
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write (reply1.getBytes());
|
||||
readAll (s);
|
||||
s.close ();
|
||||
|
||||
System.out.println ("Server 2: accept");
|
||||
s = server.accept ();
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
readAll (s);
|
||||
os.write ((reply2+"HelloWorld").getBytes());
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println (e);
|
||||
}
|
||||
finished ();
|
||||
}
|
||||
|
||||
public synchronized void finished () {
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyAuthenticator3 extends Authenticator {
|
||||
PasswordAuthentication pw;
|
||||
MyAuthenticator3 () {
|
||||
super ();
|
||||
pw = new PasswordAuthentication ("user", "passwordNotCheckedAnyway".toCharArray());
|
||||
}
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication ()
|
||||
{
|
||||
System.out.println ("Auth called");
|
||||
return pw;
|
||||
}
|
||||
|
||||
public void checkPW () {
|
||||
if (!new String (pw.getPassword()).equals ("passwordNotCheckedAnyway")) {
|
||||
throw new RuntimeException ("Password was \"" + new String (pw.getPassword()) + "\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void read (InputStream is) throws IOException {
|
||||
int c;
|
||||
System.out.println ("reading");
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write (c);
|
||||
}
|
||||
System.out.println ("");
|
||||
System.out.println ("finished reading");
|
||||
}
|
||||
|
||||
public static void main (String args[]) throws Exception {
|
||||
MyAuthenticator3 auth = new MyAuthenticator3 ();
|
||||
Authenticator.setDefault (auth);
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
int port = ss.getLocalPort ();
|
||||
BasicServer3 server = new BasicServer3 (ss);
|
||||
synchronized (server) {
|
||||
server.start();
|
||||
System.out.println ("client 1");
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(port)
|
||||
.path("/d1/d2/d3/foo.html")
|
||||
.toURL();
|
||||
URLConnection urlc = url.openConnection(Proxy.NO_PROXY);
|
||||
InputStream is = urlc.getInputStream ();
|
||||
read (is);
|
||||
is.close ();
|
||||
auth.checkPW ();
|
||||
}
|
||||
}
|
||||
}
|
||||
242
test/jdk/java/net/Authenticator/BasicTest4.java
Normal file
242
test/jdk/java/net/Authenticator/BasicTest4.java
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2024, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4623722
|
||||
* @summary performance hit for Basic Authentication
|
||||
* @library /test/lib
|
||||
* @run main/othervm BasicTest4
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true BasicTest4
|
||||
*/
|
||||
|
||||
public class BasicTest4 {
|
||||
|
||||
static class BasicServer extends Thread {
|
||||
|
||||
ServerSocket server;
|
||||
|
||||
Socket s;
|
||||
InputStream is;
|
||||
OutputStream os;
|
||||
|
||||
static final String realm = "wallyworld";
|
||||
|
||||
String reply1 = "HTTP/1.1 401 Unauthorized\r\n"+
|
||||
"WWW-Authenticate: Basic realm=\""+realm+"\"\r\n\r\n";
|
||||
|
||||
String reply2 = "HTTP/1.1 200 OK\r\n"+
|
||||
"Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +
|
||||
"Server: Apache/1.3.14 (Unix)\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n" +
|
||||
"Content-Length: 10\r\n\r\n";
|
||||
|
||||
BasicServer (ServerSocket s) {
|
||||
server = s;
|
||||
}
|
||||
|
||||
static boolean checkFor (InputStream in, char[] seq) throws IOException {
|
||||
System.out.println ("checkfor");
|
||||
StringBuilder message = new StringBuilder();
|
||||
try {
|
||||
int i=0, count=0;
|
||||
while (true) {
|
||||
int c = in.read();
|
||||
if (c == -1) {
|
||||
System.out.println(new String(seq) + " not found in \n<<"
|
||||
+ message + ">>");
|
||||
return false;
|
||||
}
|
||||
message.append((char)c);
|
||||
count++;
|
||||
if (c == seq[i]) {
|
||||
i++;
|
||||
if (i == seq.length)
|
||||
return true;
|
||||
continue;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SocketTimeoutException e) {
|
||||
System.out.println("checkFor: " + e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
|
||||
void readAll (Socket s) throws IOException {
|
||||
byte[] buf = new byte [128];
|
||||
InputStream is = s.getInputStream ();
|
||||
s.setSoTimeout(1000);
|
||||
try {
|
||||
while (is.read(buf) > 0) ;
|
||||
} catch (SocketTimeoutException x) { }
|
||||
}
|
||||
|
||||
public void run () {
|
||||
try {
|
||||
System.out.println ("Server 1: accept");
|
||||
s = server.accept ();
|
||||
readAll (s);
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write (reply1.getBytes());
|
||||
s.close ();
|
||||
|
||||
System.out.println ("Server 2: accept");
|
||||
s = server.accept ();
|
||||
readAll (s);
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write ((reply2+"HelloWorld").getBytes());
|
||||
s.close ();
|
||||
|
||||
/* Second request now */
|
||||
|
||||
System.out.println ("Server 3: accept");
|
||||
s = server.accept ();
|
||||
readAll (s);
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write (reply1.getBytes());
|
||||
s.close ();
|
||||
|
||||
System.out.println ("Server 4: accept");
|
||||
s = server.accept ();
|
||||
readAll (s);
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
os.write ((reply2+"HelloAgain").getBytes());
|
||||
s.close ();
|
||||
|
||||
/* Third request now */
|
||||
|
||||
/* This should include pre-emptive authorization */
|
||||
|
||||
System.out.println ("Server 5: accept");
|
||||
s = server.accept ();
|
||||
s.setSoTimeout (1000);
|
||||
System.out.println ("accepted");
|
||||
InputStream is = s.getInputStream ();
|
||||
success = checkFor (is, "Authorization".toCharArray());
|
||||
System.out.println ("checkfor returned " + success);
|
||||
readAll (s);
|
||||
os = s.getOutputStream();
|
||||
os.write ((reply2+"HelloAgain").getBytes());
|
||||
s.close ();
|
||||
|
||||
if (success)
|
||||
return;
|
||||
|
||||
System.out.println ("Server 6: accept");
|
||||
s = server.accept ();
|
||||
System.out.println ("accepted");
|
||||
os = s.getOutputStream();
|
||||
readAll (s);
|
||||
os.write ((reply2+"HelloAgain").getBytes());
|
||||
s.close ();
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println (e);
|
||||
}
|
||||
finished ();
|
||||
}
|
||||
|
||||
public synchronized void finished () {
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyAuthenticator extends Authenticator {
|
||||
MyAuthenticator () {
|
||||
super ();
|
||||
}
|
||||
|
||||
public PasswordAuthentication getPasswordAuthentication ()
|
||||
{
|
||||
System.out.println ("Auth called");
|
||||
return (new PasswordAuthentication ("user", "passwordNotCheckedAnyway".toCharArray()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void read (InputStream is) throws IOException {
|
||||
int c;
|
||||
System.out.println ("reading");
|
||||
while ((c=is.read()) != -1) {
|
||||
System.out.write (c);
|
||||
}
|
||||
System.out.println ("");
|
||||
System.out.println ("finished reading");
|
||||
}
|
||||
|
||||
public static void main (String args[]) throws Exception {
|
||||
MyAuthenticator auth = new MyAuthenticator ();
|
||||
Authenticator.setDefault (auth);
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
int port = ss.getLocalPort ();
|
||||
BasicServer server = new BasicServer (ss);
|
||||
synchronized (server) {
|
||||
server.start();
|
||||
System.out.println ("client 1");
|
||||
String base = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(port)
|
||||
.path("/d1/")
|
||||
.build()
|
||||
.toString();
|
||||
System.out.println("Base URL: " + base);
|
||||
URL url = new URL (base + "d3/foo.html");
|
||||
URLConnection urlc = url.openConnection(Proxy.NO_PROXY);
|
||||
InputStream is = urlc.getInputStream ();
|
||||
read (is);
|
||||
System.out.println ("client 2");
|
||||
url = new URL (base + "d2/bar.html");
|
||||
urlc = url.openConnection(Proxy.NO_PROXY);
|
||||
is = urlc.getInputStream ();
|
||||
System.out.println ("client 3");
|
||||
url = new URL (base + "d4/foobar.html");
|
||||
urlc = url.openConnection(Proxy.NO_PROXY);
|
||||
is = urlc.getInputStream ();
|
||||
read (is);
|
||||
server.wait ();
|
||||
if (!server.success) {
|
||||
throw new RuntimeException ("3rd request did not use pre-emptive authorization");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
173
test/jdk/java/net/Authenticator/Deadlock.java
Normal file
173
test/jdk/java/net/Authenticator/Deadlock.java
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6648001
|
||||
* @modules jdk.httpserver
|
||||
* @library /test/lib
|
||||
* @run main/othervm/timeout=20 -ea:sun.net.www.protocol.http.AuthenticationInfo -Dhttp.auth.serializeRequests=true Deadlock
|
||||
* @run main/othervm/timeout=20 -Djava.net.preferIPv6Addresses=true
|
||||
* -ea:sun.net.www.protocol.http.AuthenticationInfo -Dhttp.auth.serializeRequests=true Deadlock
|
||||
* @summary cancelling HTTP authentication causes deadlock
|
||||
*/
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import com.sun.net.httpserver.BasicAuthenticator;
|
||||
import com.sun.net.httpserver.Headers;
|
||||
import com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpPrincipal;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class Deadlock {
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
Handler handler = new Handler();
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
InetSocketAddress addr = new InetSocketAddress (loopback, 0);
|
||||
HttpServer server = HttpServer.create(addr, 0);
|
||||
HttpContext ctx = server.createContext("/test", handler);
|
||||
BasicAuthenticator a = new BasicAuthenticator("foobar@test.realm") {
|
||||
@Override
|
||||
public boolean checkCredentials (String username, String pw) {
|
||||
return "fred".equals(username) && pw.charAt(0) == 'x';
|
||||
}
|
||||
};
|
||||
|
||||
ctx.setAuthenticator(a);
|
||||
ExecutorService executor = Executors.newCachedThreadPool();
|
||||
server.setExecutor(executor);
|
||||
server.start ();
|
||||
java.net.Authenticator.setDefault(new MyAuthenticator());
|
||||
|
||||
System.out.print("Deadlock: " );
|
||||
for (int i=0; i<2; i++) {
|
||||
Runner t = new Runner(server, i);
|
||||
t.start();
|
||||
t.join();
|
||||
}
|
||||
server.stop(2);
|
||||
executor.shutdown();
|
||||
if (error) {
|
||||
throw new RuntimeException("test failed error");
|
||||
}
|
||||
|
||||
if (count != 2) {
|
||||
throw new RuntimeException("test failed count = " + count);
|
||||
}
|
||||
System.out.println("OK");
|
||||
|
||||
}
|
||||
|
||||
static class Runner extends Thread {
|
||||
HttpServer server;
|
||||
int i;
|
||||
Runner(HttpServer s, int i) {
|
||||
server = s;
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
URL url;
|
||||
HttpURLConnection urlc;
|
||||
try {
|
||||
url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(server.getAddress().getPort())
|
||||
.path("/test/foo.html")
|
||||
.toURLUnchecked();
|
||||
urlc = (HttpURLConnection)url.openConnection (Proxy.NO_PROXY);
|
||||
} catch (IOException e) {
|
||||
error = true;
|
||||
return;
|
||||
}
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = urlc.getInputStream();
|
||||
while (is.read()!= -1) {}
|
||||
} catch (IOException e) {
|
||||
if (i == 1) error = true;
|
||||
} finally {
|
||||
if (is != null) try { is.close(); } catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean error = false;
|
||||
public static int count = 0;
|
||||
|
||||
static class MyAuthenticator extends java.net.Authenticator {
|
||||
@Override
|
||||
public PasswordAuthentication getPasswordAuthentication() {
|
||||
PasswordAuthentication pw;
|
||||
if (!getRequestingPrompt().equals("foobar@test.realm")) {
|
||||
Deadlock.error = true;
|
||||
}
|
||||
if (count == 0) {
|
||||
pw = null;
|
||||
} else {
|
||||
pw = new PasswordAuthentication("fred", "xyz".toCharArray());
|
||||
}
|
||||
count++;
|
||||
return pw;
|
||||
}
|
||||
}
|
||||
|
||||
static class Handler implements HttpHandler {
|
||||
int invocation = 1;
|
||||
|
||||
@Override
|
||||
public void handle (HttpExchange t)
|
||||
throws IOException
|
||||
{
|
||||
InputStream is = t.getRequestBody();
|
||||
Headers map = t.getRequestHeaders();
|
||||
Headers rmap = t.getResponseHeaders();
|
||||
while (is.read() != -1);
|
||||
is.close();
|
||||
t.sendResponseHeaders(200, -1);
|
||||
HttpPrincipal p = t.getPrincipal();
|
||||
if (!p.getUsername().equals("fred")) {
|
||||
error = true;
|
||||
}
|
||||
if (!p.getRealm().equals("foobar@test.realm")) {
|
||||
error = true;
|
||||
}
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
64
test/jdk/java/net/Authenticator/GetAuthenticatorTest.java
Normal file
64
test/jdk/java/net/Authenticator/GetAuthenticatorTest.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2024, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
import java.lang.ref.Reference;
|
||||
import java.net.Authenticator;
|
||||
import java.net.PasswordAuthentication;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8169068
|
||||
* @summary Basic test for Authenticator.getDefault()
|
||||
* @run main/othervm GetAuthenticatorTest
|
||||
*/
|
||||
public class GetAuthenticatorTest {
|
||||
|
||||
static final class MyAuthenticator extends Authenticator {
|
||||
|
||||
MyAuthenticator () {
|
||||
super ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PasswordAuthentication getPasswordAuthentication () {
|
||||
System.out.println ("Auth called");
|
||||
return (new PasswordAuthentication ("user",
|
||||
"passwordNotCheckedAnyway".toCharArray()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main (String args[]) throws Exception {
|
||||
Authenticator defaultAuth = Authenticator.getDefault();
|
||||
if (defaultAuth != null) {
|
||||
throw new RuntimeException("Unexpected authenticator: null expected");
|
||||
}
|
||||
MyAuthenticator auth = new MyAuthenticator();
|
||||
Authenticator.setDefault(auth);
|
||||
defaultAuth = Authenticator.getDefault();
|
||||
if (defaultAuth != auth) {
|
||||
throw new RuntimeException("Unexpected authenticator: auth expected");
|
||||
}
|
||||
System.out.println("Test passed with default authenticator "
|
||||
+ defaultAuth);
|
||||
}
|
||||
}
|
||||
49
test/jdk/java/net/B6499348.java
Normal file
49
test/jdk/java/net/B6499348.java
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6499348
|
||||
* @summary java.net socket classes should implement java.io.Closeable
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.io.Closeable;
|
||||
|
||||
public class B6499348 {
|
||||
public static void main(String[] args) throws java.io.IOException {
|
||||
Socket s = new Socket();
|
||||
ServerSocket ss = new ServerSocket();
|
||||
DatagramSocket ds = new DatagramSocket((SocketAddress) null);
|
||||
|
||||
if (! (s instanceof Closeable))
|
||||
throw new RuntimeException("Socket is not a java.io.Closeable");
|
||||
if (! (ss instanceof Closeable))
|
||||
throw new RuntimeException("ServerSocket is not a java.io.Closeable");
|
||||
if (! (ds instanceof Closeable))
|
||||
throw new RuntimeException("DatagramSocket is not a java.io.Closeable");
|
||||
s.close();
|
||||
ss.close();
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
277
test/jdk/java/net/BindException/Test.java
Normal file
277
test/jdk/java/net/BindException/Test.java
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4417734
|
||||
* @key intermittent
|
||||
* @summary Test that we get a BindException in all expected combinations
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* @run main Test -d
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.Enumeration;
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
|
||||
public class Test {
|
||||
|
||||
static Object[][] getTestCombinations() {
|
||||
return new Object[][] {
|
||||
{ "ServerSocket", "Socket" },
|
||||
{ "Socket", "Socket" },
|
||||
{ "DatagramSocket", "DatagramSocket" },
|
||||
};
|
||||
}
|
||||
|
||||
static InetAddress ia4_this;
|
||||
static InetAddress ia6_this;
|
||||
|
||||
static int count;
|
||||
static int failures;
|
||||
static boolean retried;
|
||||
|
||||
static void doTest(Object test[], InetAddress ia1, InetAddress ia2,
|
||||
boolean silent) throws Exception {
|
||||
/*
|
||||
* Increment test count
|
||||
*/
|
||||
count++;
|
||||
|
||||
doTest(test, count, ia1, ia2, silent, !retried);
|
||||
}
|
||||
|
||||
static void doTest(Object test[], int count, InetAddress ia1, InetAddress ia2,
|
||||
boolean silent, boolean retry) throws Exception {
|
||||
String s1_type = (String)test[0];
|
||||
String s2_type = (String)test[1];
|
||||
int port = 0;
|
||||
|
||||
/*
|
||||
* Do the test
|
||||
*/
|
||||
|
||||
boolean gotBindException = false;
|
||||
boolean failed = false;
|
||||
Exception failed_exc = null;
|
||||
|
||||
Socket sock1 = null;
|
||||
ServerSocket ss = null;
|
||||
DatagramSocket dsock1 = null;
|
||||
boolean firstBound = false;
|
||||
|
||||
try {
|
||||
/* bind the first socket */
|
||||
|
||||
if (s1_type.equals("Socket")) {
|
||||
sock1 = new Socket();
|
||||
sock1.bind( new InetSocketAddress(ia1, 0));
|
||||
port = sock1.getLocalPort();
|
||||
}
|
||||
|
||||
if (s1_type.equals("ServerSocket")) {
|
||||
ss = new ServerSocket(0, 0, ia1);
|
||||
port = ss.getLocalPort();
|
||||
}
|
||||
|
||||
if (s1_type.equals("DatagramSocket")) {
|
||||
dsock1 = new DatagramSocket( new InetSocketAddress(ia1, 0) );
|
||||
port = dsock1.getLocalPort();
|
||||
}
|
||||
|
||||
/* bind the second socket */
|
||||
|
||||
// The fact that the port was available for ia1 does not
|
||||
// guarantee that it will also be available for ia2 as something
|
||||
// else might already be bound to that port.
|
||||
// For the sake of test stability we will retry once in
|
||||
// case of unexpected bind exception.
|
||||
|
||||
firstBound = true;
|
||||
if (s2_type.equals("Socket")) {
|
||||
try (Socket sock2 = new Socket()) {
|
||||
sock2.bind( new InetSocketAddress(ia2, port));
|
||||
}
|
||||
}
|
||||
|
||||
if (s2_type.equals("ServerSocket")) {
|
||||
try (ServerSocket ss2 = new ServerSocket(port, 0, ia2)) { }
|
||||
}
|
||||
|
||||
if (s2_type.equals("DatagramSocket")) {
|
||||
try (DatagramSocket ds =
|
||||
new DatagramSocket(new InetSocketAddress(ia2, port))) { }
|
||||
}
|
||||
|
||||
} catch (BindException be) {
|
||||
gotBindException = true;
|
||||
failed_exc = be;
|
||||
} catch (Exception e) {
|
||||
failed = true;
|
||||
failed_exc = e;
|
||||
} finally {
|
||||
if (sock1 != null) sock1.close();
|
||||
if (ss != null) ss.close();
|
||||
if (dsock1 != null) dsock1.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we expect a BindException?
|
||||
*/
|
||||
boolean expectedBindException = true;
|
||||
if (ia1 == ia4_this && ia2 == ia6_this) {
|
||||
expectedBindException = false;
|
||||
}
|
||||
if (ia1 == ia6_this && ia2 == ia4_this) {
|
||||
expectedBindException = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Did it fail?
|
||||
*/
|
||||
|
||||
if (!failed && gotBindException != expectedBindException) {
|
||||
failed = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If test passed and running in silent mode then exit
|
||||
*/
|
||||
if (!failed && silent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (failed && retry && firstBound) {
|
||||
// retry once at the first failure only
|
||||
retried = true;
|
||||
if (!silent) {
|
||||
System.out.println("");
|
||||
System.out.println("**************************");
|
||||
System.out.println("Test " + count + ": Retrying...");
|
||||
}
|
||||
doTest(test, count, ia1, ia2, silent, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (failed || !silent) {
|
||||
System.out.println("");
|
||||
System.out.println("**************************");
|
||||
System.out.println("Test " + count);
|
||||
|
||||
System.out.println(s1_type + " binds: " + ia1 + " port: " + port);
|
||||
System.out.println(s2_type + " binds: " + ia2);
|
||||
|
||||
if (!failed) {
|
||||
if (gotBindException) {
|
||||
System.out.println("Got expected BindException - test passed!");
|
||||
failed_exc.printStackTrace(System.out);
|
||||
} else {
|
||||
System.out.println("No BindException as expected - test passed!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (gotBindException) {
|
||||
System.out.println("BindException unexpected - test failed!!!");
|
||||
failed_exc.printStackTrace(System.out);
|
||||
} else {
|
||||
System.out.println("No bind failure as expected - test failed!!!");
|
||||
}
|
||||
failures++;
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
|
||||
boolean silent = true;
|
||||
if (args.length > 0) {
|
||||
if (args[0].equals("-d")) {
|
||||
silent = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test needs an IPv4 and IPv6 address to run.
|
||||
*/
|
||||
Enumeration nifs = NetworkInterface.getNetworkInterfaces();
|
||||
while (nifs.hasMoreElements()) {
|
||||
NetworkInterface ni = (NetworkInterface)nifs.nextElement();
|
||||
|
||||
Enumeration addrs = ni.getInetAddresses();
|
||||
while (addrs.hasMoreElements()) {
|
||||
InetAddress ia = (InetAddress)addrs.nextElement();
|
||||
|
||||
if (ia.isLoopbackAddress() || ia.isAnyLocalAddress()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((ia instanceof Inet4Address) && (ia4_this == null)) {
|
||||
ia4_this = ia;
|
||||
}
|
||||
|
||||
if ((ia instanceof Inet6Address) && (ia6_this == null)) {
|
||||
ia6_this = ia;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform tests on all combinations of IPv4 and IPv6
|
||||
* addresses.
|
||||
*/
|
||||
InetAddress addrs[] = { ia4_this, ia6_this };
|
||||
|
||||
if (!silent) {
|
||||
System.out.println("Using ia4_this:" + ia4_this);
|
||||
System.out.println("Using ia6_this:" + ia6_this);
|
||||
}
|
||||
|
||||
Object tests[][] = getTestCombinations();
|
||||
|
||||
for (int i=0; i<tests.length; i++) {
|
||||
Object test[] = tests[i];
|
||||
|
||||
for (int j=0; j<addrs.length; j++) {
|
||||
for (int k=0; k<addrs.length; k++) {
|
||||
|
||||
if (addrs[j] == null || addrs[k] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
doTest( test, addrs[j], addrs[k], silent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("");
|
||||
System.out.println(count + " test(s) executed. " + failures + " failure(s).");
|
||||
|
||||
if (failures > 0) {
|
||||
System.err.println("********************************");
|
||||
NetworkConfiguration.printSystemConfiguration(System.err);
|
||||
System.out.println("********************************");
|
||||
throw new Exception(failures + " tests(s) failed - see log");
|
||||
}
|
||||
}
|
||||
}
|
||||
60
test/jdk/java/net/CookieHandler/B6277794.java
Normal file
60
test/jdk/java/net/CookieHandler/B6277794.java
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Unit test for java.net.CookieManager API
|
||||
* @bug 6277794
|
||||
* @run main/othervm -ea B6277794
|
||||
* @author Edward Wang
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
public class B6277794 {
|
||||
public static void main(String[] args) throws Exception {
|
||||
testCookieStore();
|
||||
}
|
||||
|
||||
private static void testCookieStore() throws Exception {
|
||||
CookieManager cm = new CookieManager();
|
||||
CookieStore cs = cm.getCookieStore();
|
||||
|
||||
HttpCookie c1 = new HttpCookie("COOKIE1", "COOKIE1");
|
||||
HttpCookie c2 = new HttpCookie("COOKIE2", "COOKIE2");
|
||||
cs.add(new URI("http://www.sun.com/solaris"), c1);
|
||||
cs.add(new URI("http://www.sun.com/java"), c2);
|
||||
|
||||
List<URI> uris = cs.getURIs();
|
||||
if (uris.size() != 1 ||
|
||||
!uris.get(0).equals(new URI("http://www.sun.com"))) {
|
||||
fail("CookieStore.getURIs() fail.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void fail(String msg) throws Exception {
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
212
test/jdk/java/net/CookieHandler/B6644726.java
Normal file
212
test/jdk/java/net/CookieHandler/B6644726.java
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6644726 6873543
|
||||
* @summary Cookie management issues
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class B6644726 {
|
||||
public static void main(String[] args) throws Exception {
|
||||
testCookieStore();
|
||||
}
|
||||
|
||||
private static void testCookieStore() throws Exception {
|
||||
CookieManager cm = new CookieManager();
|
||||
CookieStore cs = cm.getCookieStore();
|
||||
URI uri = new URI("http://www.s1.sun.com/dir/foo/doc.html");
|
||||
URI suri = new URI("https://www.s1.sun.com/dir/foo/index.html");
|
||||
cm.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
|
||||
|
||||
ArrayList<String> lst = new ArrayList<String>();
|
||||
// Let's test the default path
|
||||
lst.add("myCookie1=foo");
|
||||
// Then some alternate expires format
|
||||
lst.add("myCookie2=bar; path=/dir; expires=Fri, 19 Aug 4242 16:00:00 GMT");
|
||||
lst.add("myCookie3=test; path=/dir; expires=Fri Aug 19 4242 16:00:00 GMT-0100");
|
||||
// Then Netscape draft cookies and domains
|
||||
lst.add("myCookie4=test; domain=.sun.com; path=/dir/foo");
|
||||
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
|
||||
map.put("Set-Cookie", lst);
|
||||
cm.put(uri, map);
|
||||
map.clear();
|
||||
lst.clear();
|
||||
// Test for secure tag
|
||||
lst.add("myCookie5=test; secure");
|
||||
// Test for passing cookies between http and https
|
||||
map.put("Set-Cookie", lst);
|
||||
cm.put(suri, map);
|
||||
|
||||
List<HttpCookie> cookies = cs.getCookies();
|
||||
// There should be 5 cookies if all dates parsed correctly
|
||||
if (cookies.size() != 5) {
|
||||
fail("unexpected cookies: " + cookies + ", should have 5 cookies. Got only "
|
||||
+ cookies.size() + ", expires probably didn't parse correctly");
|
||||
}
|
||||
// Check Path for first Cookie
|
||||
for (HttpCookie c : cookies) {
|
||||
if (c.getName().equals("myCookie1")) {
|
||||
if (!"/dir/foo/".equals(c.getPath())) {
|
||||
fail("Default path for myCookie1 is " + c.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HashMap<String, List<String>> emptyMap = new HashMap<String, List<String>>();
|
||||
// We should get 1 Cookie: MyCookie4, because of the domain
|
||||
Map<String, List<String>>m = cm.get(new URI("http://www.s2.sun.com/dir/foo/doc2.html"),
|
||||
emptyMap);
|
||||
List<String> clst = m.get("Cookie");
|
||||
if (clst.size() != 1) {
|
||||
fail("We should have only 1 cookie, not " + clst.size());
|
||||
} else {
|
||||
if (!clst.get(0).startsWith("myCookie4")) {
|
||||
fail("The cookie should be myCookie4, not " + clst.get(0));
|
||||
}
|
||||
}
|
||||
// We should get 4 cookies for non secure URI, and 5 for the secure one
|
||||
m = cm.get(suri, emptyMap);
|
||||
clst = m.get("Cookie");
|
||||
if (clst.size() != 5) {
|
||||
fail("Cookies didn't cross from http to https. Got only " + clst.size());
|
||||
}
|
||||
|
||||
m = cm.get(uri, emptyMap);
|
||||
clst = m.get("Cookie");
|
||||
if (clst.size() != 4) {
|
||||
fail("We should have gotten only 4 cookies over http (non secure), got " +
|
||||
clst.size());
|
||||
}
|
||||
if (isIn(clst, "myCookie5=")) {
|
||||
// myCookie5 (the secure one) shouldn't be here
|
||||
fail("Got the secure cookie over a non secure link");
|
||||
}
|
||||
|
||||
// Let's check that empty path is treated correctly
|
||||
uri = new URI("http://www.sun.com/");
|
||||
lst.clear();
|
||||
lst.add("myCookie6=foo");
|
||||
map.clear();
|
||||
map.put("Set-Cookie", lst);
|
||||
cm.put(uri, map);
|
||||
uri = new URI("http://www.sun.com");
|
||||
m = cm.get(uri, emptyMap);
|
||||
clst = m.get("Cookie");
|
||||
if (clst.size() != 1) {
|
||||
fail("Missing a cookie when using an empty path");
|
||||
}
|
||||
|
||||
// And now, the other way around:
|
||||
|
||||
uri = new URI("http://www.sun.com");
|
||||
lst.clear();
|
||||
lst.add("myCookie7=foo");
|
||||
map.clear();
|
||||
map.put("Set-Cookie", lst);
|
||||
cm.put(uri, map);
|
||||
uri = new URI("http://www.sun.com/");
|
||||
m = cm.get(uri, emptyMap);
|
||||
clst = m.get("Cookie");
|
||||
if (!isIn(clst, "myCookie7=")) {
|
||||
fail("Missing a cookie when using an empty path");
|
||||
}
|
||||
|
||||
// Let's make sure the 'Port' optional attributes is enforced
|
||||
|
||||
lst.clear();
|
||||
lst.add("myCookie8=porttest; port");
|
||||
lst.add("myCookie9=porttest; port=\"80,8000\"");
|
||||
lst.add("myCookie10=porttest; port=\"8000\"");
|
||||
map.clear();
|
||||
map.put("Set-Cookie", lst);
|
||||
uri = new URI("http://www.sun.com/");
|
||||
cm.put(uri, map);
|
||||
|
||||
// myCookie10 should have been rejected
|
||||
cookies = cs.getCookies();
|
||||
for (HttpCookie c : cookies) {
|
||||
if (c.getName().equals("myCookie10")) {
|
||||
fail("A cookie with an invalid port list was accepted");
|
||||
}
|
||||
}
|
||||
|
||||
uri = new URI("http://www.sun.com:80/");
|
||||
m = cm.get(uri, emptyMap);
|
||||
clst = m.get("Cookie");
|
||||
// We should find both myCookie8 and myCookie9 but not myCookie10
|
||||
if (!isIn(clst, "myCookie8=") || !isIn(clst, "myCookie9=")) {
|
||||
fail("Missing a cookie on port 80");
|
||||
}
|
||||
uri = new URI("http://www.sun.com:8000/");
|
||||
m = cm.get(uri, emptyMap);
|
||||
clst = m.get("Cookie");
|
||||
// We should find only myCookie9
|
||||
if (!isIn(clst, "myCookie9=")) {
|
||||
fail("Missing a cookie on port 80");
|
||||
}
|
||||
if (isIn(clst, "myCookie8=")) {
|
||||
fail("A cookie with an invalid port list was returned");
|
||||
}
|
||||
|
||||
// Test httpOnly flag (CR# 6873543)
|
||||
lst.clear();
|
||||
map.clear();
|
||||
cm.getCookieStore().removeAll();
|
||||
lst.add("myCookie11=httpOnlyTest; httpOnly");
|
||||
map.put("Set-Cookie", lst);
|
||||
uri = new URI("http://www.sun.com/");
|
||||
cm.put(uri, map);
|
||||
m = cm.get(uri, emptyMap);
|
||||
clst = m.get("Cookie");
|
||||
// URI scheme was http: so we should get the cookie
|
||||
if (!isIn(clst, "myCookie11=")) {
|
||||
fail("Missing cookie with httpOnly flag");
|
||||
}
|
||||
uri = new URI("javascript://www.sun.com/");
|
||||
m = cm.get(uri, emptyMap);
|
||||
clst = m.get("Cookie");
|
||||
// URI scheme was neither http or https so we shouldn't get the cookie
|
||||
if (isIn(clst, "myCookie11=")) {
|
||||
fail("Should get the cookie with httpOnly when scheme is javascript:");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isIn(List<String> lst, String cookie) {
|
||||
if (lst == null || lst.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (String s : lst) {
|
||||
if (s.startsWith(cookie))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void fail(String msg) throws Exception {
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
58
test/jdk/java/net/CookieHandler/B6791927.java
Normal file
58
test/jdk/java/net/CookieHandler/B6791927.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6791927 8233886
|
||||
* @summary Wrong Locale in HttpCookie::expiryDate2DeltaSeconds
|
||||
* @run main/othervm B6791927
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class B6791927 {
|
||||
public static final void main(String[] aaParamters) throws Exception {
|
||||
Locale reservedLocale = Locale.getDefault();
|
||||
try {
|
||||
// Forces a non US locale
|
||||
Locale.setDefault(Locale.FRANCE);
|
||||
List<HttpCookie> cookies = HttpCookie.parse("set-cookie:" +
|
||||
" CUSTOMER=WILE_E_COYOTE;" +
|
||||
" expires=Sat, 09-Nov-2041 23:12:40 GMT");
|
||||
if (cookies == null || cookies.isEmpty()) {
|
||||
throw new RuntimeException("No cookie found");
|
||||
}
|
||||
for (HttpCookie c : cookies) {
|
||||
if (c.getMaxAge() == 0) {
|
||||
throw new RuntimeException(
|
||||
"Expiration date shouldn't be 0");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// restore the reserved locale
|
||||
Locale.setDefault(reservedLocale);
|
||||
}
|
||||
}
|
||||
}
|
||||
149
test/jdk/java/net/CookieHandler/CookieHandlerTest.java
Normal file
149
test/jdk/java/net/CookieHandler/CookieHandlerTest.java
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @summary Unit test for java.net.CookieHandler
|
||||
* @bug 4696506
|
||||
* @library /test/lib
|
||||
* @run main/othervm CookieHandlerTest
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true CookieHandlerTest
|
||||
* @author Yingxian Wang
|
||||
*/
|
||||
|
||||
// Run in othervm since a default cookier handler is set and this
|
||||
// can effect other HTTP related tests.
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class CookieHandlerTest implements Runnable {
|
||||
static Map<String,String> cookies;
|
||||
ServerSocket ss;
|
||||
|
||||
/*
|
||||
* Our "http" server to return a 404
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
Socket s = ss.accept();
|
||||
|
||||
// check request contains "Cookie"
|
||||
InputStream is = s.getInputStream ();
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(is));
|
||||
boolean flag = false;
|
||||
String x;
|
||||
while ((x=r.readLine()) != null) {
|
||||
if (x.length() ==0) {
|
||||
break;
|
||||
}
|
||||
String header = "Cookie: ";
|
||||
if (x.startsWith(header)) {
|
||||
if (x.equals("Cookie: "+((String)cookies.get("Cookie")))) {
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
throw new RuntimeException("server should see cookie in request");
|
||||
}
|
||||
|
||||
PrintStream out = new PrintStream(
|
||||
new BufferedOutputStream(
|
||||
s.getOutputStream() ));
|
||||
|
||||
/* send the header */
|
||||
out.print("HTTP/1.1 200 OK\r\n");
|
||||
out.print("Set-Cookie2: "+((String)cookies.get("Set-Cookie2")+"\r\n"));
|
||||
out.print("Content-Type: text/html; charset=iso-8859-1\r\n");
|
||||
out.print("Connection: close\r\n");
|
||||
out.print("\r\n");
|
||||
out.print("<HTML>");
|
||||
out.print("<HEAD><TITLE>Testing cookie</TITLE></HEAD>");
|
||||
out.print("<BODY>OK.</BODY>");
|
||||
out.print("</HTML>");
|
||||
out.flush();
|
||||
|
||||
s.close();
|
||||
ss.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
CookieHandlerTest() throws Exception {
|
||||
|
||||
/* start the server */
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
(new Thread(this)).start();
|
||||
|
||||
/* establish http connection to server */
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(ss.getLocalPort())
|
||||
.toURL();
|
||||
|
||||
HttpURLConnection http = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
|
||||
|
||||
int respCode = http.getResponseCode();
|
||||
http.disconnect();
|
||||
|
||||
}
|
||||
public static void main(String args[]) throws Exception {
|
||||
cookies = new HashMap<String, String>();
|
||||
cookies.put("Cookie", "$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"");
|
||||
cookies.put("Set-Cookie2", "$Version=\"1\"; Part_Number=\"Riding_Rocket_0023\"; $Path=\"/acme/ammo\"; Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"");
|
||||
CookieHandler.setDefault(new MyCookieHandler());
|
||||
new CookieHandlerTest();
|
||||
}
|
||||
|
||||
static class MyCookieHandler extends CookieHandler {
|
||||
public Map<String,List<String>>
|
||||
get(URI uri, Map<String,List<String>> requestHeaders)
|
||||
throws IOException {
|
||||
// returns cookies[0]
|
||||
// they will be include in request
|
||||
Map<String,List<String>> map = new HashMap<String,List<String>>();
|
||||
List<String> l = new ArrayList<String>();
|
||||
l.add(cookies.get("Cookie"));
|
||||
map.put("Cookie",l);
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
public void
|
||||
put(URI uri, Map<String,List<String>> responseHeaders)
|
||||
throws IOException {
|
||||
// check response has cookies[1]
|
||||
List<String> l = responseHeaders.get("Set-Cookie2");
|
||||
String value = l.get(0);
|
||||
if (!value.equals(cookies.get("Set-Cookie2"))) {
|
||||
throw new RuntimeException("cookie should be available for handle to put into cache");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
383
test/jdk/java/net/CookieHandler/CookieManagerTest.java
Normal file
383
test/jdk/java/net/CookieHandler/CookieManagerTest.java
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Unit test for java.net.CookieManager
|
||||
* @bug 6244040 7150552 7051862
|
||||
* @modules jdk.httpserver
|
||||
* java.logging
|
||||
* @run main/othervm -ea -esa CookieManagerTest
|
||||
* @author Edward Wang
|
||||
*/
|
||||
|
||||
import com.sun.net.httpserver.*;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import static java.net.Proxy.NO_PROXY;
|
||||
|
||||
public class CookieManagerTest {
|
||||
|
||||
static CookieTransactionHandler httpTrans;
|
||||
static HttpServer server;
|
||||
|
||||
static final String hostAddress = getAddr();
|
||||
|
||||
/** Returns an IP literal suitable for use by the test. */
|
||||
static String getAddr() {
|
||||
try {
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
System.out.println("Trying: " + lh);
|
||||
if (lh.isReachable(5_000)) {
|
||||
System.out.println("Using: " + lh);
|
||||
return lh.getHostAddress();
|
||||
}
|
||||
} catch (IOException x) {
|
||||
System.out.println("Debug: caught:" + x);
|
||||
}
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
System.out.println("Using: \"" + loopback.getHostAddress() + "\"");
|
||||
return loopback.getHostAddress();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// logs everything...
|
||||
Logger root = Logger.getLogger("");
|
||||
root.setLevel(Level.ALL);
|
||||
root.getHandlers()[0].setLevel(Level.ALL);
|
||||
|
||||
startHttpServer();
|
||||
makeHttpCall();
|
||||
|
||||
if (httpTrans.badRequest) {
|
||||
throw new RuntimeException("Test failed : bad cookie header");
|
||||
}
|
||||
checkCookiePolicy();
|
||||
}
|
||||
|
||||
public static void startHttpServer() throws IOException {
|
||||
httpTrans = new CookieTransactionHandler();
|
||||
server = HttpServer.create(new InetSocketAddress(hostAddress, 0), 0);
|
||||
server.createContext("/", httpTrans);
|
||||
server.start();
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if CookiePolicy.ACCEPT_ORIGINAL_SERVER#shouldAccept()
|
||||
* returns false for null arguments
|
||||
*/
|
||||
private static void checkCookiePolicy() throws Exception {
|
||||
CookiePolicy cp = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
|
||||
boolean retVal;
|
||||
retVal = cp.shouldAccept(null, null);
|
||||
checkValue(retVal);
|
||||
retVal = cp.shouldAccept(null, new HttpCookie("CookieName", "CookieVal"));
|
||||
checkValue(retVal);
|
||||
retVal = cp.shouldAccept((new URL("http", "localhost", 2345, "/")).toURI(),
|
||||
null);
|
||||
checkValue(retVal);
|
||||
}
|
||||
|
||||
private static void checkValue(boolean val) {
|
||||
if (val)
|
||||
throw new RuntimeException("Return value is not false!");
|
||||
}
|
||||
|
||||
public static void makeHttpCall() throws IOException {
|
||||
try {
|
||||
int port = server.getAddress().getPort();
|
||||
System.out.println("http server listenining on: " + port);
|
||||
|
||||
// install CookieManager to use
|
||||
CookieHandler.setDefault(new CookieManager());
|
||||
|
||||
for (int i = 0; i < CookieTransactionHandler.testCount; i++) {
|
||||
System.out.println("====== CookieManager test " + (i+1)
|
||||
+ " ======");
|
||||
((CookieManager)CookieHandler.getDefault())
|
||||
.setCookiePolicy(CookieTransactionHandler.testPolicies[i]);
|
||||
((CookieManager)CookieHandler.getDefault())
|
||||
.getCookieStore().removeAll();
|
||||
URL url = new URL("http" ,
|
||||
hostAddress,
|
||||
server.getAddress().getPort(),
|
||||
CookieTransactionHandler.testCases[i][0]
|
||||
.serverPath);
|
||||
System.out.println("Requesting " + url);
|
||||
HttpURLConnection uc = (HttpURLConnection)url.openConnection(NO_PROXY);
|
||||
uc.getResponseCode();
|
||||
uc.disconnect();
|
||||
}
|
||||
} finally {
|
||||
server.stop(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CookieTransactionHandler implements HttpHandler {
|
||||
|
||||
private int testcaseDone = 0;
|
||||
private int testDone = 0;
|
||||
|
||||
public static boolean badRequest = false;
|
||||
// the main test control logic will also loop exactly this number
|
||||
// to send http request
|
||||
public static final int testCount = 6;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
if (testDone < testCases[testcaseDone].length) {
|
||||
// still have other tests to run,
|
||||
// check the Cookie header and then redirect it
|
||||
if (testDone > 0) checkRequest(exchange.getRequestHeaders());
|
||||
exchange.getResponseHeaders().add("Location",
|
||||
testCases[testcaseDone][testDone].serverPath);
|
||||
exchange.getResponseHeaders()
|
||||
.add(testCases[testcaseDone][testDone].headerToken,
|
||||
testCases[testcaseDone][testDone].cookieToSend);
|
||||
exchange.sendResponseHeaders(302, -1);
|
||||
testDone++;
|
||||
} else {
|
||||
// the last test of this test case
|
||||
if (testDone > 0) checkRequest(exchange.getRequestHeaders());
|
||||
testcaseDone++;
|
||||
testDone = 0;
|
||||
exchange.sendResponseHeaders(200, -1);
|
||||
}
|
||||
exchange.close();
|
||||
}
|
||||
|
||||
private static String trim(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i=0; i<s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if (!Character.isWhitespace(c))
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static boolean cookieEquals(String s1, String s2) {
|
||||
s1 = trim(s1);
|
||||
s2 = trim(s2);
|
||||
String[] s1a = s1.split(";");
|
||||
String[] s2a = s2.split(";");
|
||||
List<String> l1 = new LinkedList(List.of(s1a));
|
||||
List<String> l2 = new LinkedList(List.of(s2a));
|
||||
Collections.sort(l1);
|
||||
Collections.sort(l2);
|
||||
int i = 0;
|
||||
for (String s : l1) {
|
||||
if (!s.equals(l2.get(i++))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void checkRequest(Headers hdrs) {
|
||||
|
||||
assert testDone > 0;
|
||||
String cookieHeader = hdrs.getFirst("Cookie");
|
||||
if (cookieHeader != null && cookieEquals(
|
||||
cookieHeader, testCases[testcaseDone][testDone-1].cookieToRecv))
|
||||
{
|
||||
System.out.printf("%15s %s\n", "PASSED:", cookieHeader);
|
||||
} else {
|
||||
System.out.printf("%15s %s\n", "FAILED:", cookieHeader);
|
||||
System.out.printf("%15s %s\n\n", "should be:",
|
||||
testCases[testcaseDone][testDone-1].cookieToRecv);
|
||||
badRequest = true;
|
||||
}
|
||||
}
|
||||
|
||||
// test cases
|
||||
public static class CookieTestCase {
|
||||
public String headerToken;
|
||||
public String cookieToSend;
|
||||
public String cookieToRecv;
|
||||
public String serverPath;
|
||||
|
||||
public CookieTestCase(String h, String cts, String ctr, String sp) {
|
||||
headerToken = h;
|
||||
cookieToSend = cts;
|
||||
cookieToRecv = ctr;
|
||||
serverPath = sp;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* these two must match each other,
|
||||
* i.e. testCases.length == testPolicies.length
|
||||
*/
|
||||
|
||||
// the test cases to run; each test case may contain multiple roundtrips
|
||||
public static CookieTestCase[][] testCases = null;
|
||||
// indicates what CookiePolicy to use with each test cases
|
||||
public static CookiePolicy[] testPolicies = null;
|
||||
|
||||
CookieTransactionHandler() {
|
||||
testCases = new CookieTestCase[testCount][];
|
||||
testPolicies = new CookiePolicy[testCount];
|
||||
|
||||
String localHostAddr = CookieManagerTest.hostAddress;
|
||||
|
||||
int count = 0;
|
||||
|
||||
// an http session with Netscape cookies exchanged
|
||||
testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
|
||||
testCases[count++] = new CookieTestCase[]{
|
||||
new CookieTestCase("Set-Cookie",
|
||||
"CUSTOMER=WILE:BOB; " +
|
||||
"path=/; expires=Sat, 09-Nov-2030 23:12:40 GMT;" + "domain=." +
|
||||
localHostAddr,
|
||||
"CUSTOMER=WILE:BOB",
|
||||
"/"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie",
|
||||
"PART_NUMBER=ROCKET_LAUNCHER_0001; path=/;" + "domain=." + localHostAddr,
|
||||
"CUSTOMER=WILE:BOB; PART_NUMBER=ROCKET_LAUNCHER_0001",
|
||||
"/"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie",
|
||||
"SHIPPING=FEDEX; path=/foo;" + "domain=." + localHostAddr,
|
||||
"CUSTOMER=WILE:BOB; PART_NUMBER=ROCKET_LAUNCHER_0001",
|
||||
"/"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie",
|
||||
"SHIPPING=FEDEX; path=/foo;" + "domain=." + localHostAddr,
|
||||
"CUSTOMER=WILE:BOB; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX",
|
||||
"/foo"
|
||||
)
|
||||
};
|
||||
|
||||
// check whether or not path rule is applied
|
||||
testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
|
||||
testCases[count++] = new CookieTestCase[]{
|
||||
new CookieTestCase("Set-Cookie",
|
||||
"PART_NUMBER=ROCKET_LAUNCHER_0001; path=/;" + "domain=." + localHostAddr,
|
||||
"PART_NUMBER=ROCKET_LAUNCHER_0001",
|
||||
"/"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie",
|
||||
"PART_NUMBER=RIDING_ROCKET_0023; path=/ammo;" + "domain=." + localHostAddr,
|
||||
"PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001",
|
||||
"/ammo"
|
||||
)
|
||||
};
|
||||
|
||||
// an http session with rfc2965 cookies exchanged
|
||||
testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
|
||||
testCases[count++] = new CookieTestCase[]{
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Customer=\"WILE_E_COYOTE\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
|
||||
"$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\"." + localHostAddr + "\"",
|
||||
"/acme/login"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\";Path=\"/acme\";" + "domain=." + localHostAddr,
|
||||
"$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";" + "$Domain=\"." +
|
||||
localHostAddr + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";"
|
||||
+ "$Domain=\"." + localHostAddr + "\"",
|
||||
"/acme/pickitem"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Shipping=\"FedEx\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
|
||||
"$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr +
|
||||
"\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + "$Domain=\"."
|
||||
+ localHostAddr + "\"" + "; Shipping=\"FedEx\";$Path=\"/acme\";" +
|
||||
"$Domain=\"." + localHostAddr + "\"",
|
||||
"/acme/shipping"
|
||||
)
|
||||
};
|
||||
|
||||
// check whether or not the path rule is applied
|
||||
testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
|
||||
testCases[count++] = new CookieTestCase[]{
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
|
||||
"$Version=\"1\"; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\"." + localHostAddr + "\"",
|
||||
"/acme/ammo"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Part_Number=\"Riding_Rocket_0023\"; Version=\"1\"; Path=\"/acme/ammo\";" + "domain=."
|
||||
+ localHostAddr,
|
||||
"$Version=\"1\"; Part_Number=\"Riding_Rocket_0023\";$Path=\"/acme/ammo\";$Domain=\"."
|
||||
+ localHostAddr + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";"
|
||||
+ "$Domain=\"." + localHostAddr + "\"",
|
||||
"/acme/ammo"
|
||||
),
|
||||
new CookieTestCase("",
|
||||
"",
|
||||
"$Version=\"1\"; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr + "\"",
|
||||
"/acme/parts"
|
||||
)
|
||||
};
|
||||
|
||||
// new cookie should overwrite old cookie
|
||||
testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
|
||||
testCases[count++] = new CookieTestCase[]{
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
|
||||
"$Version=\"1\"; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\"." + localHostAddr + "\"",
|
||||
"/acme"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Part_Number=\"Rocket_Launcher_2000\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
|
||||
"$Version=\"1\"; Part_Number=\"Rocket_Launcher_2000\";$Path=\"/acme\";$Domain=\"." + localHostAddr + "\"",
|
||||
"/acme"
|
||||
)
|
||||
};
|
||||
|
||||
// cookies without domain attributes
|
||||
// RFC 2965 states that domain should default to host
|
||||
testPolicies[count] = CookiePolicy.ACCEPT_ALL;
|
||||
testCases[count++] = new CookieTestCase[]{
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Customer=\"WILE_E_COYOTE\"; Version=\"1\"; Path=\"/acme\"",
|
||||
"$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"",
|
||||
"/acme/login"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\";Path=\"/acme\"",
|
||||
"$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" +
|
||||
"; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"",
|
||||
"/acme/pickitem"
|
||||
),
|
||||
new CookieTestCase("Set-Cookie2",
|
||||
"Shipping=\"FedEx\"; Version=\"1\"; Path=\"/acme\"",
|
||||
"$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" +
|
||||
"; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" +
|
||||
"; Shipping=\"FedEx\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"",
|
||||
"/acme/shipping"
|
||||
)
|
||||
};
|
||||
|
||||
assert count == testCount;
|
||||
}
|
||||
}
|
||||
105
test/jdk/java/net/CookieHandler/EmptyCookieHeader.java
Normal file
105
test/jdk/java/net/CookieHandler/EmptyCookieHeader.java
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8015799
|
||||
* @modules jdk.httpserver
|
||||
* @summary HttpURLConnection.getHeaderFields() throws IllegalArgumentException
|
||||
* @library /test/lib
|
||||
* @run main EmptyCookieHeader
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true EmptyCookieHeader
|
||||
*/
|
||||
|
||||
import com.sun.net.httpserver.*;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class EmptyCookieHeader {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new EmptyCookieHeader().runTest();
|
||||
}
|
||||
|
||||
public void runTest() throws Exception {
|
||||
final CookieHandler oldHandler = CookieHandler.getDefault();
|
||||
CookieHandler.setDefault(new TestCookieHandler());
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
HttpServer s = HttpServer.create(new InetSocketAddress(loopback, 0), 0);
|
||||
try {
|
||||
startServer(s);
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(s.getAddress().getPort())
|
||||
.path("/")
|
||||
.toURL();
|
||||
HttpURLConnection c = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
|
||||
c.getHeaderFields();
|
||||
} finally {
|
||||
CookieHandler.setDefault(oldHandler);
|
||||
s.stop(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void startServer(HttpServer server) throws IOException {
|
||||
server.createContext("/", new EmptyCookieHandler());
|
||||
server.start();
|
||||
}
|
||||
|
||||
static class EmptyCookieHandler implements HttpHandler {
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
String requestMethod = exchange.getRequestMethod();
|
||||
if (requestMethod.equalsIgnoreCase("GET")) {
|
||||
Headers responseHeaders = exchange.getResponseHeaders();
|
||||
responseHeaders.set("Content-Type", "text/plain");
|
||||
responseHeaders.set("Date", "June 13th 2012");
|
||||
|
||||
// No domain value set
|
||||
responseHeaders.set("Set-Cookie2", "name=value");
|
||||
responseHeaders.set("Set-Cookie2", "");
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
try (OutputStream os = exchange.getResponseBody()) {
|
||||
String str = "This is what the server sent!";
|
||||
os.write(str.getBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestCookieHandler extends CookieHandler {
|
||||
@Override
|
||||
public Map<String,List<String>> get(URI uri,
|
||||
Map<String,List<String>> respH) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(URI uri, Map<String,List<String >> respH) { }
|
||||
}
|
||||
}
|
||||
131
test/jdk/java/net/CookieHandler/LocalHostCookie.java
Normal file
131
test/jdk/java/net/CookieHandler/LocalHostCookie.java
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
import com.sun.net.httpserver.*;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import static java.net.Proxy.NO_PROXY;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 7169142
|
||||
* @key intermittent
|
||||
* @modules jdk.httpserver
|
||||
* @summary CookieHandler does not work with localhost. This requires
|
||||
* binding to the wildcard address and might fail intermittently
|
||||
* due to port reuse issues.
|
||||
* @run main/othervm LocalHostCookie
|
||||
*/
|
||||
public class LocalHostCookie {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new LocalHostCookie().runTest();
|
||||
}
|
||||
|
||||
public void runTest() throws Exception {
|
||||
Server s = null;
|
||||
try {
|
||||
s = new Server();
|
||||
s.startServer();
|
||||
URL url = new URL("http","localhost", s.getPort(), "/");
|
||||
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection(NO_PROXY);
|
||||
urlConnection.setRequestMethod("GET");
|
||||
urlConnection.setDoOutput(true);
|
||||
urlConnection.connect();
|
||||
urlConnection.getInputStream();
|
||||
|
||||
CookieHandler cookieHandler = CookieHandler.getDefault();
|
||||
if (cookieHandler == null) {
|
||||
cookieHandler = new java.net.CookieManager();
|
||||
CookieHandler.setDefault(cookieHandler);
|
||||
}
|
||||
cookieHandler.put(urlConnection.getURL().toURI(),
|
||||
urlConnection.getHeaderFields());
|
||||
Map<String, List<String>> map =
|
||||
cookieHandler.get(urlConnection.getURL().toURI(),
|
||||
urlConnection.getHeaderFields());
|
||||
if (map.containsKey("Cookie")) {
|
||||
List<String> list = map.get("Cookie");
|
||||
// name-value list will be empty if ".local" is not appended
|
||||
if (list == null || list.size() == 0) {
|
||||
throw new RuntimeException("Test failed!");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (s != null) {
|
||||
s.stopServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Server {
|
||||
HttpServer server;
|
||||
|
||||
public void startServer() {
|
||||
InetSocketAddress addr = new InetSocketAddress(0);
|
||||
try {
|
||||
server = HttpServer.create(addr, 0);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Server could not be created");
|
||||
}
|
||||
|
||||
server.createContext("/", new MyCookieHandler());
|
||||
server.start();
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return server.getAddress().getPort();
|
||||
}
|
||||
|
||||
public void stopServer() {
|
||||
if (server != null) {
|
||||
server.stop(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MyCookieHandler implements HttpHandler {
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
String requestMethod = exchange.getRequestMethod();
|
||||
if (requestMethod.equalsIgnoreCase("GET")){
|
||||
Headers responseHeaders = exchange.getResponseHeaders();
|
||||
responseHeaders.set("Content-Type", "text/plain");
|
||||
responseHeaders.set("Date", "June 13th 2012");
|
||||
// No domain value set
|
||||
responseHeaders.set("Set-Cookie2", "name=value");
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
OutputStream os = exchange.getResponseBody();
|
||||
String str = "This is what the server sent!";
|
||||
os.write(str.getBytes());
|
||||
os.flush();
|
||||
os.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
86
test/jdk/java/net/CookieHandler/NullUriCookieTest.java
Normal file
86
test/jdk/java/net/CookieHandler/NullUriCookieTest.java
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6953455 7045655
|
||||
* @summary CookieStore.add() cannot handle null URI parameter
|
||||
* and An empty InMemoryCookieStore should not return true for removeAll
|
||||
*/
|
||||
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookieStore;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
|
||||
public class NullUriCookieTest {
|
||||
static boolean fail = false;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
checkCookieNullUri();
|
||||
}
|
||||
|
||||
static void checkCookieNullUri() throws Exception {
|
||||
//get a cookie store implementation and add a cookie to the store with null URI
|
||||
CookieStore cookieStore = (new CookieManager()).getCookieStore();
|
||||
//Check if removeAll() retrurns false on an empty CookieStore
|
||||
if (cookieStore.removeAll()) {
|
||||
fail = true;
|
||||
}
|
||||
checkFail("removeAll on empty store should return false");
|
||||
HttpCookie cookie = new HttpCookie("MY_COOKIE", "MY_COOKIE_VALUE");
|
||||
cookie.setDomain("foo.com");
|
||||
cookieStore.add(null, cookie);
|
||||
|
||||
//Retrieve added cookie
|
||||
URI uri = new URI("http://foo.com");
|
||||
List<HttpCookie> addedCookieList = cookieStore.get(uri);
|
||||
|
||||
//Verify CookieStore behaves well
|
||||
if (addedCookieList.size() != 1) {
|
||||
fail = true;
|
||||
}
|
||||
checkFail("Abnormal size of cookie jar");
|
||||
|
||||
for (HttpCookie chip : addedCookieList) {
|
||||
if (!chip.equals(cookie)) {
|
||||
fail = true;
|
||||
}
|
||||
}
|
||||
checkFail("Cookie not retrieved from Cookie Jar");
|
||||
boolean ret = cookieStore.remove(null,cookie);
|
||||
if (!ret) {
|
||||
fail = true;
|
||||
}
|
||||
checkFail("Abnormal removal behaviour from Cookie Jar");
|
||||
}
|
||||
|
||||
static void checkFail(String exp) {
|
||||
if (fail) {
|
||||
throw new RuntimeException(exp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
398
test/jdk/java/net/CookieHandler/TestHttpCookie.java
Normal file
398
test/jdk/java/net/CookieHandler/TestHttpCookie.java
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2013, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Unit test for java.net.HttpCookie
|
||||
* @bug 6244040 6277796 6277801 6277808 6294071 6692802 6790677 6901170 8020758
|
||||
* @author Edward Wang
|
||||
*/
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.util.List;
|
||||
|
||||
public class TestHttpCookie {
|
||||
private static int testCount = 0;
|
||||
|
||||
private String cHeader = null;
|
||||
private List<HttpCookie> cookies = null;
|
||||
|
||||
// test case here expressed as a string, which represents
|
||||
// the header string to be parsed into HttpCookie instance.
|
||||
// A TestHttpCookie instance will be created to hold such a HttpCookie
|
||||
// object, and TestHttpCookie class has utility methods to check equality
|
||||
// between HttpCookie's real property and expected property.
|
||||
static TestHttpCookie test(String cookieHeader) {
|
||||
testCount++;
|
||||
return new TestHttpCookie(cookieHeader);
|
||||
}
|
||||
|
||||
TestHttpCookie(String cHeader) {
|
||||
this.cHeader = cHeader;
|
||||
|
||||
try {
|
||||
List<HttpCookie> cookies = HttpCookie.parse(cHeader);
|
||||
this.cookies = cookies;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
cookies = null;
|
||||
}
|
||||
}
|
||||
|
||||
// check name
|
||||
TestHttpCookie n(int index, String n) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || !n.equalsIgnoreCase(cookie.getName())) {
|
||||
raiseError("name", cookie.getName(), n);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie n(String n) { return n(0, n); }
|
||||
|
||||
// check value
|
||||
TestHttpCookie v(int index, String v) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || !v.equals(cookie.getValue())) {
|
||||
raiseError("value", cookie.getValue(), v);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie v(String v) { return v(0, v); }
|
||||
|
||||
// check version
|
||||
TestHttpCookie ver(int index, int ver) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || (ver != cookie.getVersion())) {
|
||||
raiseError("version", Integer.toString(cookie.getVersion()), Integer.toString(ver));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie ver(int ver) { return ver(0, ver); }
|
||||
|
||||
// check path
|
||||
TestHttpCookie p(int index, String p) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || !p.equals(cookie.getPath())) {
|
||||
raiseError("path", cookie.getPath(), p);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie p(String p) { return p(0, p); }
|
||||
|
||||
// check null-ability
|
||||
TestHttpCookie nil() {
|
||||
if (cookies != null) {
|
||||
raiseError("Check null-ability fail");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// check comment
|
||||
TestHttpCookie c(int index, String c) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || !c.equals(cookie.getComment())) {
|
||||
raiseError("comment", cookie.getComment(), c);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie c(String c) { return c(0, c); }
|
||||
|
||||
// check comment url
|
||||
TestHttpCookie cu(int index, String cu) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || !cu.equals(cookie.getCommentURL())) {
|
||||
raiseError("comment url", cookie.getCommentURL(), cu);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie cu(String cu) { return cu(0, cu); }
|
||||
|
||||
// check discard
|
||||
TestHttpCookie dsc(int index, boolean dsc) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || (dsc != cookie.getDiscard())) {
|
||||
raiseError("discard", Boolean.toString(cookie.getDiscard()), Boolean.toString(dsc));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie dsc(boolean dsc) { return dsc(0, dsc); }
|
||||
|
||||
// check domain
|
||||
TestHttpCookie d(int index, String d) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || !d.equalsIgnoreCase(cookie.getDomain())) {
|
||||
raiseError("domain", cookie.getDomain(), d);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie d(String d) { return d(0, d); }
|
||||
|
||||
// check max-age
|
||||
TestHttpCookie a(int index, long a) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || (a != cookie.getMaxAge())) {
|
||||
raiseError("max-age", Long.toString(cookie.getMaxAge()), Long.toString(a));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie a(long a) { return a(0, a); }
|
||||
|
||||
// check port list
|
||||
TestHttpCookie port(int index, String p) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || !p.equals(cookie.getPortlist())) {
|
||||
raiseError("portlist", cookie.getPortlist(), p);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
TestHttpCookie port(String p) { return port(0, p); }
|
||||
|
||||
// check http only
|
||||
TestHttpCookie httpOnly(int index, boolean b) {
|
||||
HttpCookie cookie = cookies.get(index);
|
||||
if (cookie == null || b != cookie.isHttpOnly()) {
|
||||
raiseError("HttpOnly", String.valueOf(cookie.isHttpOnly()), String.valueOf(b));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
TestHttpCookie httpOnly(boolean b) {
|
||||
return httpOnly(0, b);
|
||||
}
|
||||
|
||||
// check equality
|
||||
static void eq(HttpCookie ck1, HttpCookie ck2, boolean same) {
|
||||
testCount++;
|
||||
if (ck1.equals(ck2) != same) {
|
||||
raiseError("Comparison inconsistent: " + ck1 + " " + ck2
|
||||
+ " should " + (same ? "equal" : "not equal"));
|
||||
}
|
||||
|
||||
int h1 = ck1.hashCode();
|
||||
int h2 = ck2.hashCode();
|
||||
if ((h1 == h2) != same) {
|
||||
raiseError("Comparison inconsistent: hashCode for " + ck1 + " " + ck2
|
||||
+ " should " + (same ? "equal" : "not equal"));
|
||||
}
|
||||
}
|
||||
|
||||
// check domainMatches()
|
||||
static void dm(String domain, String host, boolean matches) {
|
||||
testCount++;
|
||||
if (HttpCookie.domainMatches(domain, host) != matches) {
|
||||
raiseError("Host " + host + (matches?" should ":" should not ") +
|
||||
"domain-match with domain " + domain);
|
||||
}
|
||||
}
|
||||
|
||||
void raiseError(String attr, String realValue, String expectedValue) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Cookie ").append(attr).append(" is ").append(realValue).
|
||||
append(", should be ").append(expectedValue).
|
||||
append(" (").append(cHeader).append(")");
|
||||
throw new RuntimeException(sb.toString());
|
||||
}
|
||||
|
||||
static void raiseError(String prompt) {
|
||||
throw new RuntimeException(prompt);
|
||||
}
|
||||
|
||||
static void runTests() {
|
||||
rfc2965();
|
||||
netscape();
|
||||
misc();
|
||||
}
|
||||
|
||||
static void rfc2965() {
|
||||
header("Test using rfc 2965 syntax");
|
||||
|
||||
test("set-cookie2: Customer=\"WILE_E_COYOTE\"; Version=\"1\"; Path=\"/acme\"")
|
||||
.n("Customer").v("WILE_E_COYOTE").ver(1).p("/acme");
|
||||
|
||||
// whitespace between attr and = sign
|
||||
test("set-cookie2: Customer = \"WILE_E_COYOTE\"; Version = \"1\"; Path = \"/acme\"")
|
||||
.n("Customer").v("WILE_E_COYOTE").ver(1).p("/acme");
|
||||
|
||||
// $NAME is reserved; result should be null
|
||||
test("set-cookie2: $Customer = \"WILE_E_COYOTE\"; Version = \"1\"; Path = \"/acme\"")
|
||||
.nil();
|
||||
|
||||
// a 'full' cookie
|
||||
test("set-cookie2: Customer=\"WILE_E_COYOTE\"" +
|
||||
";Version=\"1\"" +
|
||||
";Path=\"/acme\"" +
|
||||
";Comment=\"this is a coyote\"" +
|
||||
";CommentURL=\"http://www.coyote.org\"" +
|
||||
";Discard" +
|
||||
";Domain=\".coyote.org\"" +
|
||||
";Max-Age=\"3600\"" +
|
||||
";Port=\"80\"" +
|
||||
";Secure")
|
||||
.n("Customer").v("WILE_E_COYOTE").ver(1).p("/acme")
|
||||
.c("this is a coyote").cu("http://www.coyote.org").dsc(true)
|
||||
.d(".coyote.org").a(3600).port("80");
|
||||
|
||||
// a 'full' cookie, without leading set-cookie2 token
|
||||
test("Customer=\"WILE_E_COYOTE\"" +
|
||||
";Version=\"1\"" +
|
||||
";Path=\"/acme\"" +
|
||||
";Comment=\"this is a coyote\"" +
|
||||
";CommentURL=\"http://www.coyote.org\"" +
|
||||
";Discard" +
|
||||
";Domain=\".coyote.org\"" +
|
||||
";Max-Age=\"3600\"" +
|
||||
";Port=\"80\"" +
|
||||
";Secure")
|
||||
.n("Customer").v("WILE_E_COYOTE").ver(1).p("/acme")
|
||||
.c("this is a coyote").cu("http://www.coyote.org").dsc(true)
|
||||
.d(".coyote.org").a(3600).port("80");
|
||||
|
||||
// empty set-cookie string
|
||||
test("").nil();
|
||||
|
||||
// NullPointerException expected
|
||||
try {
|
||||
test(null);
|
||||
} catch (NullPointerException ignored) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// bug 6277796
|
||||
test("Set-Cookie2:Customer=\"dtftest\"; Discard; Secure; Domain=\".sun.com\"; Max-Age=\"100\"; Version=\"1\"; path=\"/www\"; Port=\"80\"")
|
||||
.n("Customer").v("dtftest").ver(1).d(".sun.com").p("/www").port("80").dsc(true).a(100);
|
||||
|
||||
// bug 6277801
|
||||
test("Set-Cookie2:Customer=\"dtftest\"; Discard; Secure; Domain=\".sun.com\"; Max-Age=\"100\"; Version=\"1\"; path=\"/www\"; Port=\"80\"" +
|
||||
";Domain=\".java.sun.com\"; Max-Age=\"200\"; path=\"/javadoc\"; Port=\"8080\"")
|
||||
.n("Customer").v("dtftest").ver(1).d(".sun.com").p("/www").port("80").dsc(true).a(100);
|
||||
|
||||
// bug 6294071
|
||||
test("Set-Cookie2:Customer=\"dtftest\";Discard; Secure; Domain=\"sun.com\"; Max-Age=\"100\";Version=\"1\"; Path=\"/www\"; Port=\"80,8080\"")
|
||||
.n("Customer").v("dtftest").ver(1).d("sun.com").p("/www").port("80,8080").dsc(true).a(100);
|
||||
test("Set-Cookie2:Customer=\"developer\";Domain=\"sun.com\";Max-Age=\"100\";Path=\"/www\";Port=\"80,8080\";CommentURL=\"http://www.sun.com/java1,000,000.html\"")
|
||||
.n("Customer").v("developer").d("sun.com").p("/www").port("80,8080").a(100).cu("http://www.sun.com/java1,000,000.html");
|
||||
|
||||
// a header string contains 2 cookies
|
||||
test("Set-Cookie2:C1=\"V1\";Domain=\".sun1.com\";path=\"/www1\";Max-Age=\"100\",C2=\"V2\";Domain=\".sun2.com\";path=\"/www2\";Max-Age=\"200\"")
|
||||
.n(0, "C1").v(0, "V1").p(0, "/www1").a(0, 100).d(0, ".sun1.com")
|
||||
.n(1, "C2").v(1, "V2").p(1, "/www2").a(1, 200).d(1, ".sun2.com");
|
||||
|
||||
// Bug 6790677: Should ignore bogus attributes
|
||||
test("Set-Cookie2:C1=\"V1\";foobar").n(0, "C1").v(0, "V1");
|
||||
}
|
||||
|
||||
static void netscape() {
|
||||
header("Test using netscape cookie syntax");
|
||||
|
||||
test("set-cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT")
|
||||
.n("CUSTOMER").v("WILE_E_COYOTE").p("/").ver(0);
|
||||
|
||||
// a Netscape cookie, without set-cookie leading token
|
||||
test("CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT")
|
||||
.n("CUSTOMER").v("WILE_E_COYOTE").p("/").ver(0);
|
||||
|
||||
// a 'google' cookie
|
||||
test("Set-Cookie: PREF=ID=1eda537de48ac25d:CR=1:TM=1112868587:LM=1112868587:S=t3FPA-mT9lTR3bxU;" +
|
||||
"expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com")
|
||||
.n("PREF").v("ID=1eda537de48ac25d:CR=1:TM=1112868587:LM=1112868587:S=t3FPA-mT9lTR3bxU")
|
||||
.p("/").d(".google.com").ver(0);
|
||||
|
||||
// bug 6277796
|
||||
test("set-cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT; Secure")
|
||||
.n("CUSTOMER").v("WILE_E_COYOTE").p("/").ver(0);
|
||||
|
||||
// bug 6277801
|
||||
test("set-cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT; path=\"/acme\"")
|
||||
.n("CUSTOMER").v("WILE_E_COYOTE").p("/").ver(0);
|
||||
|
||||
// bug 6901170
|
||||
test("set-cookie: CUSTOMER=WILE_E_COYOTE; version='1'").ver(1);
|
||||
}
|
||||
|
||||
static void misc() {
|
||||
header("Test equals()");
|
||||
|
||||
// test equals()
|
||||
HttpCookie c1 = new HttpCookie("Customer", "WILE_E_COYOTE");
|
||||
c1.setDomain(".coyote.org");
|
||||
c1.setPath("/acme");
|
||||
HttpCookie c2 = (HttpCookie)c1.clone();
|
||||
eq(c1, c2, true);
|
||||
|
||||
// test equals() when domain and path are null
|
||||
c1 = new HttpCookie("Customer", "WILE_E_COYOTE");
|
||||
c2 = new HttpCookie("CUSTOMER", "WILE_E_COYOTE");
|
||||
eq(c1, c2, true);
|
||||
|
||||
// path is case-sensitive
|
||||
c1 = new HttpCookie("Customer", "WILE_E_COYOTE");
|
||||
c2 = new HttpCookie("CUSTOMER", "WILE_E_COYOTE");
|
||||
c1.setPath("/acme");
|
||||
c2.setPath("/ACME");
|
||||
eq(c1, c2, false);
|
||||
|
||||
header("Test domainMatches()");
|
||||
dm(".foo.com", "y.x.foo.com", false);
|
||||
dm(".foo.com", "x.foo.com", true);
|
||||
dm(".com", "whatever.com", false);
|
||||
dm(".com.", "whatever.com", false);
|
||||
dm(".ajax.com", "ajax.com", true);
|
||||
dm(".local", "example.local", true);
|
||||
dm("example.local", "example", true);
|
||||
|
||||
// bug 6277808
|
||||
testCount++;
|
||||
try {
|
||||
c1 = new HttpCookie("", "whatever");
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// expected exception; no-op
|
||||
}
|
||||
|
||||
// CR 6692802: HttpOnly flag
|
||||
test("set-cookie: CUSTOMER=WILE_E_COYOTE;HttpOnly").httpOnly(true);
|
||||
test("set-cookie: CUSTOMER=WILE_E_COYOTE").httpOnly(false);
|
||||
|
||||
// space disallowed in name (both Netscape and RFC2965)
|
||||
test("set-cookie: CUST OMER=WILE_E_COYOTE").nil();
|
||||
}
|
||||
|
||||
static void header(String prompt) {
|
||||
System.out.println("== " + prompt + " ==");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
runTests();
|
||||
|
||||
System.out.println("Succeeded in running " + testCount + " tests.");
|
||||
}
|
||||
}
|
||||
113
test/jdk/java/net/CookieStoreTest.java
Normal file
113
test/jdk/java/net/CookieStoreTest.java
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookieStore;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8365086
|
||||
* @summary verify that the implementation of java.net.CookieStore works
|
||||
* as expected
|
||||
* @run junit CookieStoreTest
|
||||
*/
|
||||
class CookieStoreTest {
|
||||
|
||||
// neither the scheme, host nor the port matters in this test
|
||||
private static final URI COOKIE_TEST_URI = URI.create("https://127.0.0.1:12345");
|
||||
|
||||
static List<Arguments> cookieStores() {
|
||||
final List<Arguments> params = new ArrayList<>();
|
||||
// empty CookieStore
|
||||
params.add(Arguments.of(new CookieManager().getCookieStore(), true));
|
||||
|
||||
final CookieStore cookieStore = new CookieManager().getCookieStore();
|
||||
cookieStore.add(COOKIE_TEST_URI, new HttpCookie("foo", "bar"));
|
||||
// non-empty CookieStore
|
||||
params.add(Arguments.of(cookieStore, false));
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the List returned by CookieStore.getURIs() is immutable.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("cookieStores")
|
||||
void testImmutableGetURIs(final CookieStore cookieStore, final boolean expectEmpty) {
|
||||
final List<URI> uris = cookieStore.getURIs();
|
||||
assertNotNull(uris, "CookieStore.getURIs() returned null");
|
||||
assertEquals(expectEmpty, uris.isEmpty(), "CookieStore.getURIs() returned: " + uris);
|
||||
assertImmutableList(uris, COOKIE_TEST_URI);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the List returned by CookieStore.getCookies() is immutable.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("cookieStores")
|
||||
void testImmutableGetCookies(final CookieStore cookieStore, final boolean expectEmpty) {
|
||||
final List<HttpCookie> cookies = cookieStore.getCookies();
|
||||
assertNotNull(cookies, "CookieStore.getCookies() returned null");
|
||||
assertEquals(expectEmpty, cookies.isEmpty(), "CookieStore.getCookies() returned: " + cookies);
|
||||
assertImmutableList(cookies, new HttpCookie("hello", "world"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the List returned by CookieStore.get(URI) is immutable.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("cookieStores")
|
||||
void testImmutableGetCookiesForURI(final CookieStore cookieStore, final boolean expectEmpty) {
|
||||
final List<HttpCookie> cookies = cookieStore.get(COOKIE_TEST_URI);
|
||||
assertNotNull(cookies, "CookieStore.get(URI) returned null");
|
||||
assertEquals(expectEmpty, cookies.isEmpty(), "CookieStore.get(URI) returned: " + cookies);
|
||||
assertImmutableList(cookies, new HttpCookie("hello", "world"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Verifies that the attempt to modify the contents of the list will fail
|
||||
* due to the list being immutable.
|
||||
*/
|
||||
private static <T> void assertImmutableList(final List<T> list, T elementToAddOrRemove) {
|
||||
// the list is expected to be immutable, so each of these operations must fail
|
||||
assertThrows(UnsupportedOperationException.class, () -> list.add(elementToAddOrRemove));
|
||||
assertThrows(UnsupportedOperationException.class, () -> list.remove(elementToAddOrRemove));
|
||||
assertThrows(UnsupportedOperationException.class, list::clear);
|
||||
// even try the replace operation when the list isn't empty
|
||||
if (!list.isEmpty()) {
|
||||
assertThrows(UnsupportedOperationException.class, () -> list.set(0, elementToAddOrRemove));
|
||||
}
|
||||
}
|
||||
}
|
||||
43
test/jdk/java/net/DatagramPacket/CheckBoundaries.java
Normal file
43
test/jdk/java/net/DatagramPacket/CheckBoundaries.java
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 6464024
|
||||
* @summary DatagramPacket suffers from integer overflow in buffer checks.
|
||||
*/
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
public class CheckBoundaries {
|
||||
public static void main(String[] args) {
|
||||
boolean exception = false;
|
||||
try {
|
||||
final int offset = Integer.MAX_VALUE;
|
||||
final int length = 1;
|
||||
new DatagramPacket(new byte[1024], offset, length);
|
||||
} catch (IllegalArgumentException e) {
|
||||
exception = true;
|
||||
}
|
||||
if (!exception)
|
||||
throw new RuntimeException("IllegalArgumentException not thrown!");
|
||||
}
|
||||
}
|
||||
131
test/jdk/java/net/DatagramPacket/Constructor.java
Normal file
131
test/jdk/java/net/DatagramPacket/Constructor.java
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2020, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4091803 7021373
|
||||
* @summary this tests that the constructor of DatagramPacket rejects
|
||||
* bogus arguments properly.
|
||||
* @run testng Constructor
|
||||
*/
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
public class Constructor {
|
||||
|
||||
private static final byte[] buf = new byte[128];
|
||||
|
||||
private static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
|
||||
private static final Class<NullPointerException> NPE = NullPointerException.class;
|
||||
private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
|
||||
|
||||
@Test
|
||||
public void testNullPacket() {
|
||||
expectThrows(NPE,
|
||||
() -> new DatagramPacket(null, 100));
|
||||
}
|
||||
@Test
|
||||
public void testNull() throws Exception {
|
||||
expectThrows(NPE, () -> new DatagramPacket(null, 100));
|
||||
expectThrows(NPE, () -> new DatagramPacket(null, 0, 10));
|
||||
expectThrows(NPE, () -> new DatagramPacket(null, 0, 10, LOOPBACK, 80));
|
||||
expectThrows(NPE, () -> new DatagramPacket(null, 10, LOOPBACK, 80));
|
||||
expectThrows(NPE, () -> new DatagramPacket(null, 0, 10, new InetSocketAddress(80)));
|
||||
expectThrows(NPE, () -> new DatagramPacket(null, 10, new InetSocketAddress(80)));
|
||||
|
||||
// no Exception expected for null addresses
|
||||
new DatagramPacket(buf, 10, null, 0);
|
||||
new DatagramPacket(buf, 10, 10, null, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativeBufferLength() {
|
||||
/* length lesser than buffer length */
|
||||
expectThrows(IAE,
|
||||
() -> new DatagramPacket(buf, -128));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPacketLengthTooLarge() {
|
||||
/* length greater than buffer length */
|
||||
expectThrows(IAE,
|
||||
() -> new DatagramPacket(buf, 256));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativePortValue() throws Exception {
|
||||
/* negative port */
|
||||
InetAddress addr = InetAddress.getLocalHost();
|
||||
|
||||
expectThrows(IAE,
|
||||
() -> new DatagramPacket(buf, 100, addr, -1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPortValueTooLarge() {
|
||||
/* invalid port value */
|
||||
expectThrows(IAE,
|
||||
() -> new DatagramPacket(buf, 128, LOOPBACK, Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleConstructor() {
|
||||
int offset = 10;
|
||||
int length = 50;
|
||||
DatagramPacket pkt = new DatagramPacket(buf, offset, length);
|
||||
|
||||
assertFalse((pkt.getData() != buf || pkt.getOffset() != offset ||
|
||||
pkt.getLength() != length), "simple constructor failed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFullConstructor() {
|
||||
int offset = 10;
|
||||
int length = 50;
|
||||
int port = 8080;
|
||||
DatagramPacket packet = new DatagramPacket(buf, offset, length, LOOPBACK, port);
|
||||
|
||||
assertFalse((packet.getData() != buf || packet.getOffset() != offset ||
|
||||
packet.getLength() != length ||
|
||||
packet.getAddress() != LOOPBACK ||
|
||||
packet.getPort() != port), "full constructor failed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultValues() {
|
||||
DatagramPacket packet = new DatagramPacket(buf, 0);
|
||||
assertTrue(packet.getAddress() == null);
|
||||
assertTrue(packet.getPort() == 0);
|
||||
|
||||
DatagramPacket packet1 = new DatagramPacket(buf, 0, 0);
|
||||
assertTrue(packet1.getAddress() == null);
|
||||
assertTrue(packet1.getPort() == 0);
|
||||
}
|
||||
}
|
||||
47
test/jdk/java/net/DatagramPacket/Getters.java
Normal file
47
test/jdk/java/net/DatagramPacket/Getters.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8237890
|
||||
* @summary Check that DatagramPacket's get methods perform as expected
|
||||
* @run testng Getters
|
||||
*/
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
public class Getters {
|
||||
|
||||
@Test
|
||||
public void testDefaultGetSocketAddress() {
|
||||
DatagramPacket packet = new DatagramPacket(new byte[128], 0);
|
||||
InetSocketAddress addr = (InetSocketAddress)packet.getSocketAddress();
|
||||
|
||||
assertTrue(addr.getAddress().isAnyLocalAddress());
|
||||
assertTrue(addr.getPort() == 0);
|
||||
}
|
||||
}
|
||||
45
test/jdk/java/net/DatagramPacket/Offset.java
Normal file
45
test/jdk/java/net/DatagramPacket/Offset.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4203729
|
||||
* @summary Make sure that setData(byte[]) method resets offet
|
||||
*/
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
public class Offset {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
|
||||
byte b1[] = new byte[1024];
|
||||
DatagramPacket p = new DatagramPacket(b1, 512, 512 );
|
||||
|
||||
byte b2[] = new byte[20];
|
||||
p.setData(b2);
|
||||
|
||||
if (p.getOffset() != 0) {
|
||||
throw new Exception("setData(byte[]) didn't reset offset");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
152
test/jdk/java/net/DatagramPacket/ReuseBuf.java
Normal file
152
test/jdk/java/net/DatagramPacket/ReuseBuf.java
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2026, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4424096
|
||||
* @summary Verify the specification of DatagramPacket.getData()
|
||||
*/
|
||||
public class ReuseBuf {
|
||||
private static final String[] msgs = {"Hello World", "Java", "Good Bye"};
|
||||
|
||||
static class Server implements Runnable, AutoCloseable {
|
||||
|
||||
private final DatagramSocket ds;
|
||||
private volatile boolean closed;
|
||||
private final AtomicReference<Exception> serverFailure = new AtomicReference<>();
|
||||
|
||||
public Server(final InetSocketAddress bindAddr) {
|
||||
try {
|
||||
this.ds = new DatagramSocket(bindAddr);
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println("Server bound to address: " + this.ds.getLocalSocketAddress());
|
||||
}
|
||||
|
||||
private InetSocketAddress getServerAddress() {
|
||||
return (InetSocketAddress) this.ds.getLocalSocketAddress();
|
||||
}
|
||||
|
||||
private static void serverLog(final String msg) {
|
||||
System.out.println("[server] " + msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
serverLog("server processing started");
|
||||
try {
|
||||
doRun();
|
||||
} catch (Exception e) {
|
||||
// no need to be concerned with the exception
|
||||
// if the server is already closed
|
||||
if (!closed) {
|
||||
this.serverFailure.set(e);
|
||||
System.err.println("server exception: " + e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
private void doRun() throws Exception {
|
||||
byte[] b = new byte[100];
|
||||
DatagramPacket dp = new DatagramPacket(b, b.length);
|
||||
while (!closed) {
|
||||
serverLog("waiting to receive a message at " + ds.getLocalSocketAddress());
|
||||
ds.receive(dp);
|
||||
String reply = new String(dp.getData(), dp.getOffset(), dp.getLength());
|
||||
serverLog("replying to " + dp.getAddress() + ":" + dp.getPort());
|
||||
ds.send(new DatagramPacket(reply.getBytes(), reply.length(),
|
||||
dp.getAddress(), dp.getPort()));
|
||||
if (reply.equals(msgs[msgs.length - 1])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
System.out.println("Server closing " + ds.getLocalSocketAddress());
|
||||
this.ds.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
InetSocketAddress loopbackEphemeral = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
|
||||
Server server;
|
||||
Thread serverThread;
|
||||
try (var _ = server = new Server(loopbackEphemeral);
|
||||
DatagramSocket ds = new DatagramSocket(loopbackEphemeral)) {
|
||||
|
||||
InetSocketAddress destAddr = server.getServerAddress();
|
||||
// start the server
|
||||
serverThread = new Thread(server);
|
||||
serverThread.start();
|
||||
|
||||
byte[] b = new byte[100];
|
||||
DatagramPacket dp = new DatagramPacket(b, b.length);
|
||||
for (String msg : msgs) {
|
||||
System.out.println("sending message from " + ds.getLocalSocketAddress()
|
||||
+ " to " + destAddr);
|
||||
ds.send(new DatagramPacket(msg.getBytes(), msg.length(), destAddr));
|
||||
// wait for a reply from the server
|
||||
ds.receive(dp);
|
||||
System.out.println("received message from: " + dp.getAddress() + ":" + dp.getPort());
|
||||
String actual = new String(dp.getData(), dp.getOffset(), dp.getLength());
|
||||
if (!msg.equals(actual)) {
|
||||
throw new RuntimeException("Msg expected: " + msg
|
||||
+ " of length: " + msg.length() +
|
||||
", actual received: " + actual + " of length: " + dp.getLength());
|
||||
}
|
||||
}
|
||||
System.out.println("All " + msgs.length + " replies received from the server");
|
||||
}
|
||||
// wait for the server thread to complete
|
||||
System.out.println("awaiting server thread " + serverThread + " to complete");
|
||||
serverThread.join();
|
||||
Exception serverFailure = server.serverFailure.get();
|
||||
if (serverFailure != null) {
|
||||
System.err.println("Unexpected failure on server: " + serverFailure);
|
||||
throw serverFailure;
|
||||
}
|
||||
}
|
||||
}
|
||||
135
test/jdk/java/net/DatagramPacket/Setters.java
Normal file
135
test/jdk/java/net/DatagramPacket/Setters.java
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 7021373
|
||||
* @summary check that the DatagramPacket setter methods
|
||||
* throw the correct exceptions
|
||||
* @run testng Setters
|
||||
*/
|
||||
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
public class Setters {
|
||||
|
||||
private static final byte[] buf = new byte[128];
|
||||
|
||||
private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
|
||||
private static final Class<NullPointerException> NPE = NullPointerException.class;
|
||||
|
||||
@Test
|
||||
public void testSetAddress() throws Exception {
|
||||
DatagramPacket pkt = new DatagramPacket(buf, 8);
|
||||
|
||||
// No Exception expected for null addresses
|
||||
pkt.setAddress(null);
|
||||
assertTrue(pkt.getAddress() == null);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
Object[][] data() { // add checks for setAddress with null - add getAddress to verify
|
||||
return new Object[][]{
|
||||
{ buf, 0, -1, IAE },
|
||||
{ buf, -1, 1, IAE },
|
||||
{ buf, 128, 128, IAE },
|
||||
{ null, 0, 0, NPE },
|
||||
{ new byte[8], 2, 2, null },
|
||||
{ buf, 2, 2, null },
|
||||
{ buf, 20, 20, null },
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "data")
|
||||
public void testSetData(byte[] buf,
|
||||
int offset,
|
||||
int length,
|
||||
Class<? extends Exception> exception) {
|
||||
DatagramPacket pkt = new DatagramPacket(new byte[8], 8);
|
||||
|
||||
if (exception != null) {
|
||||
expectThrows(exception, () -> pkt.setData(buf, offset, length));
|
||||
} else if (buf == null) {
|
||||
expectThrows(exception, () -> pkt.setData(buf));
|
||||
} else {
|
||||
pkt.setData(buf, offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
Object[][] lengths() {
|
||||
return new Object[][]{
|
||||
{ 0, -1, IAE },
|
||||
{ 8, 1, IAE },
|
||||
{ 4, -2, IAE },
|
||||
{ 0, 9, IAE },
|
||||
{ 2, 2, null },
|
||||
{ 4, 4, null }
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "lengths")
|
||||
public void testSetLength(int offset, int length,
|
||||
Class<? extends Exception> exception) {
|
||||
DatagramPacket pkt = new DatagramPacket(new byte[8], offset, 0);
|
||||
|
||||
if (exception != null) {
|
||||
expectThrows(exception, () -> pkt.setLength(length));
|
||||
} else {
|
||||
pkt.setLength(length);
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
Object[][] ports() {
|
||||
return new Object[][]{
|
||||
{ -1, IAE },
|
||||
{ -666, IAE },
|
||||
{ Integer.MAX_VALUE, IAE },
|
||||
{ 0xFFFF + 1, IAE },
|
||||
{ 0xFFFFFF, IAE },
|
||||
{ 0, null },
|
||||
{ 1, null },
|
||||
{ 666, null },
|
||||
{ 0xFFFE, null },
|
||||
{ 0xFFFF, null },
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "ports")
|
||||
public void testSetPort(int port, Class<? extends Exception> exception) {
|
||||
DatagramPacket pkt = new DatagramPacket(new byte[8], 0);
|
||||
|
||||
if (exception != null) {
|
||||
expectThrows(exception, () -> pkt.setPort(port));
|
||||
} else {
|
||||
pkt.setPort(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
test/jdk/java/net/DatagramPacket/Unresolved.java
Normal file
44
test/jdk/java/net/DatagramPacket/Unresolved.java
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2004, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @bug 5021519
|
||||
*
|
||||
* @summary java.lang.NullPointerException: null buffer || null address
|
||||
*/
|
||||
import java.net.*;
|
||||
|
||||
public class Unresolved {
|
||||
public static void main(String[] args) throws Exception {
|
||||
InetSocketAddress remAddr = InetSocketAddress.createUnresolved( "foo.bar", 161 );
|
||||
try {
|
||||
DatagramPacket packet1 = new DatagramPacket( "Hellooo!".getBytes(), "Hellooo!".length(), remAddr );
|
||||
} catch (IllegalArgumentException e) {
|
||||
// OK! We do expect that
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("Setting an unresolved address in a DatagramPacket shouldn't be allowed");
|
||||
}
|
||||
}
|
||||
112
test/jdk/java/net/DatagramSocket/AddressNotSet.java
Normal file
112
test/jdk/java/net/DatagramSocket/AddressNotSet.java
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8233141
|
||||
* @summary DatagramSocket.send should throw IllegalArgumentException
|
||||
* when the packet address is not correctly set.
|
||||
* @run main AddressNotSet
|
||||
*/
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
import static java.lang.System.out;
|
||||
|
||||
public class AddressNotSet {
|
||||
|
||||
final InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
|
||||
final DatagramSocket serversock;
|
||||
int i;
|
||||
AddressNotSet() throws Exception {
|
||||
serversock = new DatagramSocket(0, loopbackAddress);
|
||||
}
|
||||
|
||||
public static void main (String args[]) throws Exception {
|
||||
new AddressNotSet().run();
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
try (var ss = serversock) {
|
||||
try (DatagramSocket sock = new DatagramSocket()) {
|
||||
test(sock);
|
||||
}
|
||||
try (DatagramSocket sock = new MulticastSocket()) {
|
||||
test(sock);
|
||||
}
|
||||
try (DatagramSocket sock = DatagramChannel.open().socket()) {
|
||||
test(sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void test(DatagramSocket sock) throws Exception {
|
||||
out.println("Testing with " + sock.getClass());
|
||||
InetAddress addr = loopbackAddress;
|
||||
byte[] buf;
|
||||
DatagramPacket p;
|
||||
int port = serversock.getLocalPort();
|
||||
SocketAddress connectedAddress = serversock.getLocalSocketAddress();
|
||||
|
||||
out.println("Checking send to non-connected address ...");
|
||||
try {
|
||||
out.println("Checking send with no packet address");
|
||||
buf = ("Hello, server"+(++i)).getBytes();
|
||||
p = new DatagramPacket(buf, buf.length);
|
||||
sock.send(p);
|
||||
throw new AssertionError("Expected IllegalArgumentException not received");
|
||||
} catch (IllegalArgumentException x) {
|
||||
out.println("Got expected exception: " + x);
|
||||
}
|
||||
|
||||
out.println("Checking send to valid address");
|
||||
buf = ("Hello, server"+(++i)).getBytes();
|
||||
p = new DatagramPacket(buf, buf.length, addr, port);
|
||||
sock.send(p);
|
||||
serversock.receive(p);
|
||||
|
||||
out.println("Connecting to server address: " + connectedAddress);
|
||||
sock.connect(connectedAddress);
|
||||
|
||||
try {
|
||||
out.println("Checking send with different address than connected");
|
||||
buf = ("Hello, server"+(++i)).getBytes();
|
||||
p = new DatagramPacket(buf, buf.length, addr, port+1);
|
||||
sock.send(p);
|
||||
throw new AssertionError("Expected IllegalArgumentException not received");
|
||||
} catch (IllegalArgumentException x) {
|
||||
out.println("Got expected exception: " + x);
|
||||
}
|
||||
|
||||
out.println("Checking send to valid address");
|
||||
buf = ("Hello, server"+(++i)).getBytes();
|
||||
p = new DatagramPacket(buf, buf.length, addr, port);
|
||||
sock.send(p);
|
||||
serversock.receive(p);
|
||||
}
|
||||
}
|
||||
93
test/jdk/java/net/DatagramSocket/B6411513.java
Normal file
93
test/jdk/java/net/DatagramSocket/B6411513.java
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6411513
|
||||
* @summary java.net.DatagramSocket.receive: packet isn't received
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class B6411513 {
|
||||
|
||||
public static void main( String[] args ) throws Exception {
|
||||
Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();
|
||||
while (nics.hasMoreElements()) {
|
||||
NetworkInterface nic = nics.nextElement();
|
||||
if (nic.isUp() && !nic.isVirtual()) {
|
||||
Enumeration<InetAddress> addrs = nic.getInetAddresses();
|
||||
while (addrs.hasMoreElements()) {
|
||||
InetAddress addr = addrs.nextElement();
|
||||
|
||||
// Currently, seems there's a bug on Linux that one is
|
||||
// unable to get IPv6 datagrams to be received by an
|
||||
// IPv6 socket bound to any address except ::1. So filter
|
||||
// out IPv6 address here. The test should be revisited
|
||||
// later when aforementioned bug gets fixed.
|
||||
if (addr instanceof Inet4Address) {
|
||||
System.out.printf("%s : %s\n", nic.getName(), addr);
|
||||
testConnectedUDP(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Connect a UDP socket, disconnect it, then send and recv on it.
|
||||
* It will fail on Linux if we don't silently bind(2) again at the
|
||||
* end of DatagramSocket.disconnect().
|
||||
*/
|
||||
private static void testConnectedUDP(InetAddress addr) throws Exception {
|
||||
try {
|
||||
DatagramSocket s = new DatagramSocket(0, addr);
|
||||
DatagramSocket ss = new DatagramSocket(0, addr);
|
||||
System.out.print("\tconnect...");
|
||||
s.connect(ss.getLocalAddress(), ss.getLocalPort());
|
||||
System.out.print("disconnect...");
|
||||
s.disconnect();
|
||||
|
||||
System.out.println("local addr: " + s.getLocalAddress());
|
||||
System.out.println("local port: " + s.getLocalPort());
|
||||
|
||||
byte[] data = { 0, 1, 2 };
|
||||
DatagramPacket p = new DatagramPacket(data, data.length,
|
||||
s.getLocalAddress(), s.getLocalPort());
|
||||
s.setSoTimeout( 10000 );
|
||||
System.out.print("send...");
|
||||
s.send( p );
|
||||
System.out.print("recv...");
|
||||
s.receive( p );
|
||||
System.out.println("OK");
|
||||
|
||||
ss.close();
|
||||
s.close();
|
||||
} catch( Exception e ){
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
test/jdk/java/net/DatagramSocket/B8035653.java
Normal file
42
test/jdk/java/net/DatagramSocket/B8035653.java
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8035653
|
||||
* @run main/othervm -Xcheck:jni B8035653
|
||||
* @summary InetAddress.getLocalHost crash
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class B8035653 {
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (DatagramSocket ds = new DatagramSocket();){
|
||||
ds.getLocalAddress();
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
47
test/jdk/java/net/DatagramSocket/BindFailTest.java
Normal file
47
test/jdk/java/net/DatagramSocket/BindFailTest.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test 1.1 98/08/06
|
||||
* @bug 4326262
|
||||
* @summary test that a bind failure doesn't consume an fd until
|
||||
* the datagramsocket finalizer runs.
|
||||
*/
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.BindException;
|
||||
import java.net.SocketException;
|
||||
|
||||
public class BindFailTest {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
DatagramSocket s = new DatagramSocket();
|
||||
int port = s.getLocalPort();
|
||||
|
||||
for (int i=0; i<32000; i++) {
|
||||
try {
|
||||
DatagramSocket s2 = new DatagramSocket(port);
|
||||
} catch (BindException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
95
test/jdk/java/net/DatagramSocket/ConnectPortZero.java
Normal file
95
test/jdk/java/net/DatagramSocket/ConnectPortZero.java
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2024, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8240533
|
||||
* @summary Check that DatagramSocket, MulticastSocket and DatagramSocketAdaptor
|
||||
* throw expected Exception when connecting to port 0
|
||||
* @run testng/othervm ConnectPortZero
|
||||
*/
|
||||
|
||||
public class ConnectPortZero {
|
||||
private InetAddress loopbackAddr, wildcardAddr;
|
||||
private DatagramSocket datagramSocket, datagramSocketAdaptor;
|
||||
private MulticastSocket multicastSocket;
|
||||
|
||||
private static final Class<SocketException> SE = SocketException.class;
|
||||
private static final Class<UncheckedIOException> UCIOE = UncheckedIOException.class;
|
||||
|
||||
@BeforeTest
|
||||
public void setUp() throws IOException {
|
||||
loopbackAddr = InetAddress.getLoopbackAddress();
|
||||
wildcardAddr = new InetSocketAddress(0).getAddress();
|
||||
|
||||
datagramSocket = new DatagramSocket();
|
||||
multicastSocket = new MulticastSocket();
|
||||
datagramSocketAdaptor = DatagramChannel.open().socket();
|
||||
}
|
||||
|
||||
@DataProvider(name = "data")
|
||||
public Object[][] variants() {
|
||||
return new Object[][]{
|
||||
{ datagramSocket, loopbackAddr },
|
||||
{ datagramSocketAdaptor, loopbackAddr },
|
||||
{ multicastSocket, loopbackAddr },
|
||||
{ datagramSocket, wildcardAddr },
|
||||
{ datagramSocketAdaptor, wildcardAddr },
|
||||
{ multicastSocket, wildcardAddr }
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "data")
|
||||
public void testConnect(DatagramSocket ds, InetAddress addr) {
|
||||
Throwable t = expectThrows(UCIOE, () -> ds.connect(addr, 0));
|
||||
assertEquals(t.getCause().getClass(), SE);
|
||||
|
||||
assertThrows(SE, () -> ds
|
||||
.connect(new InetSocketAddress(addr, 0)));
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void tearDown() {
|
||||
datagramSocket.close();
|
||||
multicastSocket.close();
|
||||
datagramSocketAdaptor.close();
|
||||
}
|
||||
}
|
||||
79
test/jdk/java/net/DatagramSocket/Constructor.java
Normal file
79
test/jdk/java/net/DatagramSocket/Constructor.java
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8243507 8243999
|
||||
* @summary Checks to ensure that DatagramSocket constructors behave as expected
|
||||
* @run testng Constructor
|
||||
*/
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
import static org.testng.Assert.assertThrows;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
public class Constructor {
|
||||
private static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
|
||||
private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
|
||||
|
||||
private class TestSocketAddress extends SocketAddress {
|
||||
TestSocketAddress() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindAddress() {
|
||||
var addr = new TestSocketAddress();
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new DatagramSocket(addr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidPortRange() {
|
||||
var invalidPortValues = new int[]{-1, 65536, Integer.MAX_VALUE};
|
||||
for (int i : invalidPortValues) {
|
||||
assertThrows(IAE, () -> new DatagramSocket(i));
|
||||
assertThrows(IAE, () -> new DatagramSocket(i, LOOPBACK));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDSNullAddress() throws IOException {
|
||||
try (var ds = new DatagramSocket()) {
|
||||
assertTrue(ds.getLocalAddress().isAnyLocalAddress());
|
||||
}
|
||||
|
||||
try (var ds1 = new DatagramSocket(null)) {
|
||||
assertTrue(ds1.getLocalAddress().isAnyLocalAddress());
|
||||
}
|
||||
|
||||
try (var ds2 = new DatagramSocket(0, null)) {
|
||||
assertTrue(ds2.getLocalAddress().isAnyLocalAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
174
test/jdk/java/net/DatagramSocket/DatagramSocketExample.java
Normal file
174
test/jdk/java/net/DatagramSocket/DatagramSocketExample.java
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8237352
|
||||
* @summary Verifies that the examples using DatagramSocket for
|
||||
* sending and receiving multicast datagrams are functional.
|
||||
* See "Multicasting with DatagramSocket" API note in
|
||||
* DatagramSocket.java
|
||||
*
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.net.IPSupport
|
||||
* @run main/othervm DatagramSocketExample
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true DatagramSocketExample
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketOption;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
import static java.net.StandardProtocolFamily.INET;
|
||||
import static java.net.StandardProtocolFamily.INET6;
|
||||
import static java.net.StandardSocketOptions.IP_MULTICAST_IF;
|
||||
import static java.net.StandardSocketOptions.IP_MULTICAST_LOOP;
|
||||
import static java.net.StandardSocketOptions.IP_MULTICAST_TTL;
|
||||
import static java.net.StandardSocketOptions.SO_REUSEADDR;
|
||||
|
||||
public class DatagramSocketExample {
|
||||
static final ProtocolFamily UNSPEC = () -> "UNSPEC";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
|
||||
// IPv4 and IPv6 interfaces that support multicasting
|
||||
NetworkConfiguration config = NetworkConfiguration.probe();
|
||||
List<NetworkInterface> ip4MulticastInterfaces = config.ip4MulticastInterfaces()
|
||||
.collect(Collectors.toList());
|
||||
List<NetworkInterface> ip6MulticastInterfaces = config.ip6MulticastInterfaces()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// multicast groups used for the test
|
||||
InetAddress ip4Group = InetAddress.getByName("225.4.5.6");
|
||||
InetAddress ip6Group = InetAddress.getByName("ff02::a");
|
||||
|
||||
for (NetworkInterface ni : ip4MulticastInterfaces) {
|
||||
test(INET, ip4Group, ni);
|
||||
if (IPSupport.hasIPv6()) {
|
||||
test(UNSPEC, ip4Group, ni);
|
||||
test(INET6, ip4Group, ni);
|
||||
}
|
||||
}
|
||||
for (NetworkInterface ni : ip6MulticastInterfaces) {
|
||||
test(UNSPEC, ip6Group, ni);
|
||||
test(INET6, ip6Group, ni);
|
||||
}
|
||||
}
|
||||
|
||||
static void test(ProtocolFamily family, InetAddress mcastaddr, NetworkInterface ni)
|
||||
throws IOException
|
||||
{
|
||||
System.out.format("Test family=%s, multicast group=%s, interface=%s%n",
|
||||
family.name(), mcastaddr, ni.getName());
|
||||
|
||||
// An instance of DatagramSocket can also be used to receive
|
||||
// multicast datagram packets. A DatagramSocket that is created
|
||||
// with the intent of receiving multicast datagrams should be
|
||||
// created unbound. Before binding the socket, setReuseAddress(true)
|
||||
// should be configured:
|
||||
try (DatagramSocket socket = new DatagramSocket(null); // unbound
|
||||
DatagramSocket sender = new DatagramSocket(new InetSocketAddress(0))) {
|
||||
|
||||
socket.setReuseAddress(true);
|
||||
socket.bind(new InetSocketAddress(0));
|
||||
|
||||
// joinGroup
|
||||
// InetAddress mcastaddr = InetAddress.getByName("228.5.6.7");
|
||||
InetSocketAddress group = new InetSocketAddress(mcastaddr, 0);
|
||||
// NetworkInterface netIf = NetworkInterface.getByName("en0");
|
||||
NetworkInterface netIf = ni;
|
||||
|
||||
socket.joinGroup(group, netIf);
|
||||
try {
|
||||
byte[] rcvBytes = new byte[1024]; // up to 1024 bytes
|
||||
DatagramPacket packet = new DatagramPacket(rcvBytes, rcvBytes.length);
|
||||
|
||||
// An instance of DatagramSocket can be used to send or receive
|
||||
// multicast datagram packets. Before sending out datagram packets,
|
||||
// the default outgoing interface for sending datagram packets
|
||||
// should be configured first using setOption and
|
||||
// StandardSocketOptions.IP_MULTICAST_IF:
|
||||
|
||||
// DatagramSocket sender = new DatagramSocket(new InetSocketAddress(0));
|
||||
// NetworkInterface outgoingIf = NetworkInterface.getByName("en0");
|
||||
NetworkInterface outgoingIf = ni;
|
||||
sender.setOption(StandardSocketOptions.IP_MULTICAST_IF, outgoingIf);
|
||||
|
||||
// optionally configure multicast TTL
|
||||
int ttl = 1; // a number betwen 0 and 255
|
||||
sender.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
|
||||
|
||||
// send a packet to a multicast group
|
||||
byte[] msgBytes = "Hello".getBytes(StandardCharsets.UTF_8);
|
||||
int port = socket.getLocalPort();
|
||||
InetSocketAddress dest = new InetSocketAddress(mcastaddr, port);
|
||||
DatagramPacket hi = new DatagramPacket(msgBytes, msgBytes.length, dest);
|
||||
sender.send(hi);
|
||||
|
||||
socket.receive(packet);
|
||||
byte[] bytes = Arrays.copyOfRange(packet.getData(), 0, packet.getLength());
|
||||
assertTrue("Hello".equals(new String(bytes, StandardCharsets.UTF_8)));
|
||||
} finally {
|
||||
// eventually leave group
|
||||
socket.leaveGroup(group, netIf);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void assertTrue(boolean e) {
|
||||
if (!e) throw new RuntimeException();
|
||||
}
|
||||
|
||||
interface ThrowableRunnable {
|
||||
void run() throws Exception;
|
||||
}
|
||||
|
||||
static void assertThrows(java.lang.Class<?> exceptionClass, ThrowableRunnable task) {
|
||||
try {
|
||||
task.run();
|
||||
throw new RuntimeException("Exception not thrown");
|
||||
} catch (Exception e) {
|
||||
if (!exceptionClass.isInstance(e)) {
|
||||
throw new RuntimeException("expected: " + exceptionClass + ", actual: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
379
test/jdk/java/net/DatagramSocket/DatagramSocketMulticasting.java
Normal file
379
test/jdk/java/net/DatagramSocket/DatagramSocketMulticasting.java
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8237352
|
||||
* @summary Test DatagramSocket for sending and receiving multicast datagrams
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.net.IPSupport
|
||||
* @run junit/othervm DatagramSocketMulticasting
|
||||
* @run junit/othervm -Djava.net.preferIPv4Stack=true DatagramSocketMulticasting
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketOption;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.net.StandardProtocolFamily.INET;
|
||||
import static java.net.StandardProtocolFamily.INET6;
|
||||
import static java.net.StandardSocketOptions.IP_MULTICAST_IF;
|
||||
import static java.net.StandardSocketOptions.IP_MULTICAST_LOOP;
|
||||
import static java.net.StandardSocketOptions.IP_MULTICAST_TTL;
|
||||
import static java.net.StandardSocketOptions.SO_REUSEADDR;
|
||||
import static jdk.test.lib.NetworkConfiguration.isSameInterface;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
public class DatagramSocketMulticasting {
|
||||
static final ProtocolFamily UNSPEC = () -> "UNSPEC";
|
||||
static final int MAX_TRIES = 3;
|
||||
|
||||
@Test
|
||||
public void main() throws IOException {
|
||||
assumeTrue(IPSupport.currentConfigurationIsValid(), "Invalid networking configuration");
|
||||
|
||||
// IPv4 and IPv6 interfaces that support multicasting
|
||||
NetworkConfiguration config = NetworkConfiguration.probe();
|
||||
List<NetworkInterface> ip4MulticastInterfaces = config.ip4MulticastInterfaces()
|
||||
.collect(Collectors.toList());
|
||||
List<NetworkInterface> ip6MulticastInterfaces = config.ip6MulticastInterfaces()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// multicast groups used for the test
|
||||
InetAddress ip4Group = InetAddress.getByName("225.4.5.6");
|
||||
InetAddress ip6Group = InetAddress.getByName("ff02::a");
|
||||
|
||||
for (NetworkInterface ni : ip4MulticastInterfaces) {
|
||||
test(INET, ip4Group, ni);
|
||||
if (IPSupport.hasIPv6()) {
|
||||
test(UNSPEC, ip4Group, ni);
|
||||
test(INET6, ip4Group, ni);
|
||||
}
|
||||
}
|
||||
for (NetworkInterface ni : ip6MulticastInterfaces) {
|
||||
test(UNSPEC, ip6Group, ni);
|
||||
test(INET6, ip6Group, ni);
|
||||
}
|
||||
}
|
||||
|
||||
static void test(ProtocolFamily family, InetAddress group, NetworkInterface ni)
|
||||
throws IOException
|
||||
{
|
||||
System.out.format("Test family=%s, multicast group=%s, interface=%s%n",
|
||||
family.name(), group, ni.getName());
|
||||
|
||||
// test 2-arg joinGroup/leaveGroup
|
||||
try (DatagramSocket s = create()) {
|
||||
testJoinGroup2(family, s, group, ni);
|
||||
}
|
||||
|
||||
// test socket options
|
||||
try (DatagramSocket s = create()) {
|
||||
testNetworkInterface(s, ni);
|
||||
testTimeToLive(s);
|
||||
testLoopbackMode(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MulticastSocket. The SO_REUSEADDR socket option is set and it
|
||||
* is bound to the wildcard address.
|
||||
*/
|
||||
static DatagramSocket create() throws IOException {
|
||||
DatagramSocket ds = new DatagramSocket(null);
|
||||
try {
|
||||
ds.setOption(SO_REUSEADDR, true).bind(new InetSocketAddress(0));
|
||||
} catch (IOException ioe) {
|
||||
ds.close();
|
||||
throw ioe;
|
||||
}
|
||||
return ds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test 2-arg joinGroup/leaveGroup
|
||||
*/
|
||||
static void testJoinGroup2(ProtocolFamily family,
|
||||
DatagramSocket s,
|
||||
InetAddress group,
|
||||
NetworkInterface ni) throws IOException {
|
||||
|
||||
System.out.format("testJoinGroup2: local socket address: %s%n", s.getLocalSocketAddress());
|
||||
|
||||
// check network interface not set
|
||||
assertNull(s.getOption(IP_MULTICAST_IF));
|
||||
|
||||
// join on default interface
|
||||
s.joinGroup(new InetSocketAddress(group, 0), null);
|
||||
|
||||
// join should not change the outgoing multicast interface
|
||||
assertNull(s.getOption(IP_MULTICAST_IF));
|
||||
|
||||
// already a member (exception not specified)
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.joinGroup(new InetSocketAddress(group, 0), null));
|
||||
|
||||
// leave
|
||||
s.leaveGroup(new InetSocketAddress(group, 0), null);
|
||||
|
||||
// not a member (exception not specified)
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.leaveGroup(new InetSocketAddress(group, 0), null));
|
||||
|
||||
// join on specified interface
|
||||
s.joinGroup(new InetSocketAddress(group, 0), ni);
|
||||
|
||||
// join should not change the outgoing multicast interface
|
||||
assertNull(s.getOption(IP_MULTICAST_IF));
|
||||
|
||||
// already a member (exception not specified)
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.joinGroup(new InetSocketAddress(group, 0), ni));
|
||||
|
||||
// leave
|
||||
s.leaveGroup(new InetSocketAddress(group, 0), ni);
|
||||
|
||||
// not a member (exception not specified)
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.leaveGroup(new InetSocketAddress(group, 0), ni));
|
||||
|
||||
// join/leave with outgoing multicast interface set and check that
|
||||
// multicast datagrams can be sent and received
|
||||
s.setOption(IP_MULTICAST_IF, ni);
|
||||
s.joinGroup(new InetSocketAddress(group, 0), null);
|
||||
testSendReceive(s, group);
|
||||
s.leaveGroup(new InetSocketAddress(group, 0), null);
|
||||
testSendNoReceive(s, group);
|
||||
s.joinGroup(new InetSocketAddress(group, 0), ni);
|
||||
testSendReceive(s, group);
|
||||
s.leaveGroup(new InetSocketAddress(group, 0), ni);
|
||||
testSendNoReceive(s, group);
|
||||
|
||||
// not a multicast address
|
||||
var localHost = InetAddress.getLocalHost();
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.joinGroup(new InetSocketAddress(localHost, 0), null));
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.leaveGroup(new InetSocketAddress(localHost, 0), null));
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.joinGroup(new InetSocketAddress(localHost, 0), ni));
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.leaveGroup(new InetSocketAddress(localHost, 0), ni));
|
||||
|
||||
// not an InetSocketAddress
|
||||
var customSocketAddress = new SocketAddress() { };
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.joinGroup(customSocketAddress, null));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.leaveGroup(customSocketAddress, null));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.joinGroup(customSocketAddress, ni));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.leaveGroup(customSocketAddress, ni));
|
||||
|
||||
// IPv4 socket cannot join IPv6 group
|
||||
if (family == INET && !IPSupport.hasIPv6()) {
|
||||
System.out.println("Test IPv4 can't join IPv6");
|
||||
InetAddress ip6Group = InetAddress.getByName("ff02::a");
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.joinGroup(new InetSocketAddress(ip6Group, 0), null));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.joinGroup(new InetSocketAddress(ip6Group, 0), ni));
|
||||
|
||||
// not a member of IPv6 group (exception not specified)
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.leaveGroup(new InetSocketAddress(ip6Group, 0), null));
|
||||
assertThrows(SocketException.class,
|
||||
() -> s.leaveGroup(new InetSocketAddress(ip6Group, 0), ni));
|
||||
}
|
||||
|
||||
// null
|
||||
assertThrows(IllegalArgumentException.class, () -> s.joinGroup(null, null));
|
||||
assertThrows(IllegalArgumentException.class, () -> s.leaveGroup(null, null));
|
||||
assertThrows(IllegalArgumentException.class, () -> s.joinGroup(null, ni));
|
||||
assertThrows(IllegalArgumentException.class, () -> s.leaveGroup(null, ni));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getNetworkInterface/setNetworkInterface/getInterface/setInterface
|
||||
* and IP_MULTICAST_IF socket option.
|
||||
*/
|
||||
static void testNetworkInterface(DatagramSocket s,
|
||||
NetworkInterface ni) throws IOException {
|
||||
// default value
|
||||
assertNull(s.getOption(IP_MULTICAST_IF));
|
||||
|
||||
// setOption(IP_MULTICAST_IF)
|
||||
s.setOption(IP_MULTICAST_IF, ni);
|
||||
assertTrue(isSameInterface(s.getOption(IP_MULTICAST_IF), ni));
|
||||
|
||||
// bad values for IP_MULTICAST_IF
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.setOption(IP_MULTICAST_IF, null));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.setOption((SocketOption) IP_MULTICAST_IF, "badValue"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getTimeToLive/setTimeToLive and IP_MULTICAST_TTL socket
|
||||
* option.
|
||||
*/
|
||||
static void testTimeToLive(DatagramSocket s) throws IOException {
|
||||
// should be 1 by default
|
||||
assertEquals(1, s.getOption(IP_MULTICAST_TTL));
|
||||
|
||||
// setOption(IP_MULTICAST_TTL)
|
||||
for (int ttl = 0; ttl <= 2; ttl++) {
|
||||
s.setOption(IP_MULTICAST_TTL, ttl);
|
||||
assertEquals(ttl, s.getOption(IP_MULTICAST_TTL));
|
||||
}
|
||||
|
||||
// bad values for IP_MULTICAST_TTL
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.setOption(IP_MULTICAST_TTL, -1));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.setOption(IP_MULTICAST_TTL, null));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.setOption((SocketOption) IP_MULTICAST_TTL, "badValue"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getLoopbackMode/setLoopbackMode and IP_MULTICAST_LOOP socket option.
|
||||
*/
|
||||
static void testLoopbackMode(DatagramSocket s) throws IOException {
|
||||
// should be enabled by default
|
||||
assertTrue(s.getOption(IP_MULTICAST_LOOP));
|
||||
|
||||
// setLoopbackMode
|
||||
|
||||
// setOption(IP_MULTICAST_LOOP)
|
||||
s.setOption(IP_MULTICAST_LOOP, false); // disable
|
||||
assertFalse(s.getOption(IP_MULTICAST_LOOP));
|
||||
s.setOption(IP_MULTICAST_LOOP, true); // enable
|
||||
assertTrue(s.getOption(IP_MULTICAST_LOOP));
|
||||
|
||||
// bad values for IP_MULTICAST_LOOP
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.setOption(IP_MULTICAST_LOOP, null));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> s.setOption((SocketOption) IP_MULTICAST_LOOP, "badValue"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a datagram to the given multicast group and check that it is received.
|
||||
*/
|
||||
static void testSendReceive(DatagramSocket s, InetAddress group) throws IOException {
|
||||
|
||||
System.out.println("testSendReceive");
|
||||
|
||||
// outgoing multicast interface needs to be set
|
||||
assertNotNull(s.getOption(IP_MULTICAST_IF));
|
||||
|
||||
SocketAddress target = new InetSocketAddress(group, s.getLocalPort());
|
||||
String message = "testSendReceive";
|
||||
byte[] messageBytes = message.getBytes("UTF-8");
|
||||
|
||||
// send message to multicast group
|
||||
DatagramPacket p = new DatagramPacket(messageBytes, messageBytes.length);
|
||||
p.setSocketAddress(target);
|
||||
s.send(p);
|
||||
|
||||
// receive message with retry in case of stray messages
|
||||
s.setSoTimeout(0);
|
||||
for (int i = 1; i <= MAX_TRIES; i++) {
|
||||
p = new DatagramPacket(new byte[1024], 100);
|
||||
s.receive(p);
|
||||
String messageReceived = new String(p.getData(), 0, p.getLength(), "UTF-8");
|
||||
|
||||
System.out.format(
|
||||
"TestSendReceive iteration [%s], Received DatagramPacket [%s] from [%s]%n",
|
||||
i, messageReceived, s.getLocalSocketAddress());
|
||||
|
||||
if (s.getLocalPort() == p.getPort()) {
|
||||
assertEquals(message, messageReceived,
|
||||
String.format("expected message %s, instead received %s%n",
|
||||
message, messageReceived));
|
||||
break;
|
||||
}
|
||||
|
||||
assertNotEquals(MAX_TRIES, i, "testSendReceive: too many retries");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a datagram to the given multicast group and check that it is not
|
||||
* received.
|
||||
*/
|
||||
static void testSendNoReceive(DatagramSocket s, InetAddress group) throws IOException {
|
||||
|
||||
System.out.println("testSendNoReceive");
|
||||
|
||||
// outgoing multicast interface needs to be set
|
||||
assertNotNull(s.getOption(IP_MULTICAST_IF));
|
||||
|
||||
SocketAddress target = new InetSocketAddress(group, s.getLocalPort());
|
||||
long nano = System.nanoTime();
|
||||
String text = nano + ": testSendNoReceive";
|
||||
byte[] message = text.getBytes("UTF-8");
|
||||
|
||||
// send datagram to multicast group
|
||||
DatagramPacket p = new DatagramPacket(message, message.length);
|
||||
p.setSocketAddress(target);
|
||||
s.send(p);
|
||||
|
||||
// datagram should not be received
|
||||
s.setSoTimeout(500);
|
||||
p = new DatagramPacket(new byte[1024], 100);
|
||||
while (true) {
|
||||
try {
|
||||
s.receive(p);
|
||||
if (Arrays.equals(p.getData(), p.getOffset(), p.getLength(), message, 0, message.length)) {
|
||||
throw new RuntimeException("message shouldn't have been received");
|
||||
} else {
|
||||
String messageReceived = new String(p.getData(), 0, p.getLength(), "UTF-8");
|
||||
System.out.format("Received unexpected message %s from %s%n",
|
||||
messageReceived, p.getSocketAddress());
|
||||
}
|
||||
} catch (SocketTimeoutException expected) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
115
test/jdk/java/net/DatagramSocket/DatagramTimeout.java
Normal file
115
test/jdk/java/net/DatagramSocket/DatagramTimeout.java
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4163126 8222829
|
||||
* @summary Test to see if timeout hangs. Also checks that
|
||||
* negative timeout value fails as expected.
|
||||
* @run testng DatagramTimeout
|
||||
*/
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
public class DatagramTimeout {
|
||||
private static final Class<IllegalArgumentException> IAE =
|
||||
IllegalArgumentException.class;
|
||||
private static final Class<SocketTimeoutException> STE =
|
||||
SocketTimeoutException.class;
|
||||
private static final Class<SocketException> SE = SocketException.class;
|
||||
|
||||
private DatagramSocket datagramSocket, multicastSocket,
|
||||
datagramSocketAdaptor;
|
||||
|
||||
@BeforeTest
|
||||
public void setUp() throws Exception {
|
||||
datagramSocket = new DatagramSocket();
|
||||
multicastSocket = new MulticastSocket();
|
||||
datagramSocketAdaptor = DatagramChannel.open().socket();
|
||||
}
|
||||
|
||||
@DataProvider(name = "data")
|
||||
public Object[][] variants() {
|
||||
return new Object[][]{
|
||||
{ datagramSocket },
|
||||
{ datagramSocketAdaptor },
|
||||
{ multicastSocket },
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "data")
|
||||
public void testSetNegTimeout(DatagramSocket ds) {
|
||||
assertThrows(IAE, () -> ds.setSoTimeout(-1));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "data")
|
||||
public void testSetTimeout(DatagramSocket ds) throws Exception {
|
||||
byte[] buffer = new byte[50];
|
||||
DatagramPacket pkt = new DatagramPacket(buffer, buffer.length);
|
||||
ds.setSoTimeout(2);
|
||||
assertThrows(STE, () -> ds.receive(pkt));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "data")
|
||||
public void testGetTimeout(DatagramSocket ds) throws Exception {
|
||||
ds.setSoTimeout(10);
|
||||
assertEquals(10, ds.getSoTimeout());
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void tearDown() {
|
||||
datagramSocket.close();
|
||||
multicastSocket.close();
|
||||
datagramSocketAdaptor.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetGetAfterClose() throws Exception {
|
||||
var ds = new DatagramSocket();
|
||||
var ms = new MulticastSocket();
|
||||
var dsa = DatagramChannel.open().socket();
|
||||
|
||||
ds.close();
|
||||
ms.close();
|
||||
dsa.close();
|
||||
assertThrows(SE, () -> ds.setSoTimeout(10));
|
||||
assertThrows(SE, () -> ds.getSoTimeout());
|
||||
assertThrows(SE, () -> ms.setSoTimeout(10));
|
||||
assertThrows(SE, () -> ms.getSoTimeout());
|
||||
assertThrows(SE, () -> dsa.setSoTimeout(10));
|
||||
assertThrows(SE, () -> dsa.getSoTimeout());
|
||||
}
|
||||
}
|
||||
144
test/jdk/java/net/DatagramSocket/GetLocalAddress.java
Normal file
144
test/jdk/java/net/DatagramSocket/GetLocalAddress.java
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @run main/othervm GetLocalAddress
|
||||
* @summary Check that getLocalAddress() and getLocalSocketAddress()
|
||||
* work as specified
|
||||
*/
|
||||
|
||||
public class GetLocalAddress {
|
||||
static final Map<DatagramSocket, InetAddress> addressMap = new LinkedHashMap<>();
|
||||
static final Set<DatagramSocket> toClose = new LinkedHashSet<>();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try {
|
||||
testAllSockets();
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
static void testAllSockets() throws IOException {
|
||||
var address = new InetSocketAddress(InetAddress.getLocalHost(), 0);
|
||||
bindAndAddToMap(new DatagramSocket(null), address);
|
||||
bindAndAddToMap(new MulticastSocket(null), address);
|
||||
bindAndAddToMap(DatagramChannel.open().socket(), address);
|
||||
addToMap(new DatagramSocket(address));
|
||||
addToMap(new MulticastSocket(address));
|
||||
addToMap(DatagramChannel.open().bind(address).socket());
|
||||
testSocket();
|
||||
testAfterClose();
|
||||
}
|
||||
|
||||
static void bindAndAddToMap(DatagramSocket socket, InetSocketAddress address)
|
||||
throws IOException
|
||||
{
|
||||
toClose.add(socket);
|
||||
testNullAddress(socket, socket.getLocalSocketAddress(), "before bind");
|
||||
testWildcardAddress(socket, socket.getLocalAddress(), "before bind");
|
||||
socket.bind(address);
|
||||
addressMap.put(socket, ((InetSocketAddress)socket.getLocalSocketAddress())
|
||||
.getAddress());
|
||||
}
|
||||
|
||||
static void addToMap(DatagramSocket socket) throws IOException {
|
||||
toClose.add(socket);
|
||||
addressMap.put(socket, ((InetSocketAddress)socket.getLocalSocketAddress())
|
||||
.getAddress());
|
||||
}
|
||||
|
||||
static void testSocket() throws IOException {
|
||||
for (var entry : addressMap.entrySet()) {
|
||||
var socket = entry.getKey();
|
||||
checkAddresses(socket, entry.getValue(),
|
||||
((InetSocketAddress)entry.getKey().getLocalSocketAddress())
|
||||
.getAddress());
|
||||
checkAddresses(socket, entry.getValue(),
|
||||
entry.getKey().getLocalAddress());
|
||||
}
|
||||
}
|
||||
|
||||
static void testAfterClose() throws IOException {
|
||||
for (var entry : addressMap.entrySet()) {
|
||||
var socket = entry.getKey();
|
||||
socket.close();
|
||||
toClose.remove(socket);
|
||||
testNullAddress(socket, socket.getLocalSocketAddress(), "after close");
|
||||
testNullAddress(socket, socket.getLocalAddress(), "after close");
|
||||
}
|
||||
}
|
||||
|
||||
static void checkAddresses(DatagramSocket socket, InetAddress a1, InetAddress a2) {
|
||||
System.out.println(socket.getClass() + ": Address1: "
|
||||
+ a1.toString() + " Address2: " + a2.toString());
|
||||
if (!a1.getHostAddress().equals(a2.getHostAddress()))
|
||||
{
|
||||
throw new RuntimeException("Local address don't match for " + socket.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
static void testNullAddress(DatagramSocket socket, Object address, String when) {
|
||||
System.out.println(socket.getClass() + ": Checking address " + when);
|
||||
if (address != null) {
|
||||
throw new RuntimeException("Expected null address " + when + ", got: "
|
||||
+ address + " for " + socket.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
static void testWildcardAddress(DatagramSocket socket, InetAddress address, String when) {
|
||||
System.out.println(socket.getClass() + ": Checking address " + when);
|
||||
if (address == null || !address.isAnyLocalAddress()) {
|
||||
throw new RuntimeException("Expected wildcard address " + when + ", got: "
|
||||
+ address + " for " + socket.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup() {
|
||||
// Some socket might not have been closed if
|
||||
// the test failed in exception.
|
||||
// forcing cleanup here.
|
||||
toClose.forEach(GetLocalAddress::close);
|
||||
toClose.clear();
|
||||
addressMap.clear();
|
||||
}
|
||||
|
||||
static void close(DatagramSocket socket) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (Throwable ignore) { }
|
||||
}
|
||||
|
||||
}
|
||||
48
test/jdk/java/net/DatagramSocket/ImplicitBind.java
Normal file
48
test/jdk/java/net/DatagramSocket/ImplicitBind.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4500266
|
||||
* @summary DatagramSocket.isBound reports 'false' when socket implicitly bound
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
public class ImplicitBind {
|
||||
public static void main(String[] args) throws Exception {
|
||||
DatagramSocket s = new DatagramSocket((SocketAddress)null);
|
||||
byte b[] = "hello".getBytes();
|
||||
InetAddress ia = InetAddress.getByName("localhost");
|
||||
DatagramPacket pac = new DatagramPacket(b, b.length, ia, 53);
|
||||
s.send(pac);
|
||||
if (!s.isBound())
|
||||
throw new RuntimeException("Socket should be implictly bound!");
|
||||
s.close();
|
||||
s = new DatagramSocket((SocketAddress)null);
|
||||
s.connect(new InetSocketAddress("localhost", 1234));
|
||||
if (!s.isBound())
|
||||
throw new RuntimeException("Socket should be implictly bound!");
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
72
test/jdk/java/net/DatagramSocket/InheritHandle.java
Normal file
72
test/jdk/java/net/DatagramSocket/InheritHandle.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2004, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4945514 8042581
|
||||
* @summary DatagramSocket should make handle not inherited
|
||||
*/
|
||||
|
||||
import java.net.BindException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class InheritHandle {
|
||||
private static final long SLEEPTIME_MS = 1000L;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port;
|
||||
try (DatagramSocket sock = new DatagramSocket(0);) {
|
||||
sock.setReuseAddress(true);
|
||||
port = sock.getLocalPort();
|
||||
|
||||
/**
|
||||
* spawn a child to check whether handle passed to it or not; it
|
||||
* shouldn't
|
||||
*/
|
||||
Runtime.getRuntime().exec("sleep 10");
|
||||
}
|
||||
|
||||
try (DatagramSocket sock = new DatagramSocket(null);) {
|
||||
sock.setReuseAddress(true);
|
||||
int retries = 0;
|
||||
boolean isWindows = System.getProperty("os.name").startsWith("Windows");
|
||||
InetSocketAddress addr = new InetSocketAddress(port);
|
||||
while (true) {
|
||||
try {
|
||||
sock.bind(addr);
|
||||
break;
|
||||
} catch (BindException e) {
|
||||
if (isWindows && retries++ < 5) {
|
||||
Thread.sleep(SLEEPTIME_MS);
|
||||
System.out.println("BindException \"" + e.getMessage() + "\", retrying...");
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.channels.ClosedByInterruptException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import static java.lang.Thread.sleep;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Check interrupt mechanism for DatagramSocket,
|
||||
* MulticastSocket, and DatagramSocketAdaptor
|
||||
* @library /test/lib
|
||||
* @run main InterruptibleDatagramSocket
|
||||
*/
|
||||
|
||||
public class InterruptibleDatagramSocket {
|
||||
private static void test0(DatagramSocket s) throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
Thread testThread = Thread.currentThread();
|
||||
|
||||
Thread coordinator = new Thread(() -> {
|
||||
try {
|
||||
latch.await();
|
||||
sleep(500);
|
||||
testThread.interrupt();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
});
|
||||
byte[] data = {0, 1, 2};
|
||||
DatagramPacket p = new DatagramPacket(data, data.length,
|
||||
s.getLocalAddress(), s.getLocalPort());
|
||||
s.setSoTimeout(2000);
|
||||
coordinator.start();
|
||||
latch.countDown();
|
||||
try {
|
||||
s.receive(p);
|
||||
System.out.println("Received data " + Arrays.toString(p.getData())
|
||||
+ " from " + p.getSocketAddress());
|
||||
} finally {
|
||||
try {
|
||||
coordinator.join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test(DatagramSocket s, boolean interruptible) throws Exception {
|
||||
try {
|
||||
test0(s);
|
||||
throw new RuntimeException("Receive shouldn't have succeeded");
|
||||
} catch (SocketTimeoutException e) {
|
||||
if (interruptible)
|
||||
throw e;
|
||||
System.out.println("Got expected SocketTimeoutException: " + e);
|
||||
} catch (SocketException e) {
|
||||
if ((e.getCause() instanceof ClosedByInterruptException) && interruptible) {
|
||||
System.out.println("Got expected ClosedByInterruptException: " + e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
} catch (ClosedByInterruptException e) {
|
||||
if (!interruptible)
|
||||
throw e;
|
||||
System.out.println("Got expected ClosedByInterruptException: " + e);
|
||||
}
|
||||
if (s.isClosed() && !interruptible)
|
||||
throw new RuntimeException("DatagramSocket should not be closed");
|
||||
else if (!s.isClosed() && interruptible)
|
||||
throw new RuntimeException("DatagramSocket should be closed");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (Thread.currentThread().isVirtual()) {
|
||||
throw new jtreg.SkippedException(
|
||||
"skipping test execution - main thread is a virtual thread");
|
||||
}
|
||||
try (DatagramSocket s = new DatagramSocket()) {
|
||||
System.out.println("Testing interrupt of DatagramSocket receive " +
|
||||
"on endpoint " + s.getLocalSocketAddress());
|
||||
test(s, false);
|
||||
}
|
||||
try (DatagramSocket s = new MulticastSocket()) {
|
||||
System.out.println("Testing interrupt of MulticastSocket receive" +
|
||||
" on endpoint " + s.getLocalSocketAddress());
|
||||
test(s, false);
|
||||
}
|
||||
try (DatagramSocket s = DatagramChannel.open().bind(null).socket()) {
|
||||
System.out.println("Testing interrupt of DatagramChannel socket " +
|
||||
"receive on endpoint " + s.getLocalSocketAddress());
|
||||
test(s, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
71
test/jdk/java/net/DatagramSocket/LocalSocketAddress.java
Normal file
71
test/jdk/java/net/DatagramSocket/LocalSocketAddress.java
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 6718504
|
||||
* @summary IN6_IS_ADDR_ANY tests only 12 bytes of 16-byte address
|
||||
*/
|
||||
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.*;
|
||||
|
||||
public class LocalSocketAddress {
|
||||
public static void main(String[] args) throws SocketException {
|
||||
InetAddress IPv6LoopbackAddr = null;
|
||||
DatagramSocket soc = null;
|
||||
|
||||
try {
|
||||
List<NetworkInterface> nics = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
for (NetworkInterface nic : nics) {
|
||||
if (!nic.isLoopback())
|
||||
continue;
|
||||
|
||||
List<InetAddress> addrs = Collections.list(nic.getInetAddresses());
|
||||
for (InetAddress addr : addrs) {
|
||||
if (addr instanceof Inet6Address) {
|
||||
IPv6LoopbackAddr = addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IPv6LoopbackAddr == null) {
|
||||
System.out.println("IPv6 is not available, exiting test.");
|
||||
return;
|
||||
}
|
||||
|
||||
soc = new DatagramSocket(0, IPv6LoopbackAddr);
|
||||
|
||||
if (!IPv6LoopbackAddr.equals(soc.getLocalAddress())) {
|
||||
throw new RuntimeException("Bound address is " + soc.getLocalAddress() +
|
||||
", but should be " + IPv6LoopbackAddr);
|
||||
}
|
||||
} finally {
|
||||
if (soc != null) { soc.close(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
170
test/jdk/java/net/DatagramSocket/OldDatagramSocketImplTest.java
Normal file
170
test/jdk/java/net/DatagramSocket/OldDatagramSocketImplTest.java
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8260428
|
||||
* @summary Drop support for pre JDK 1.4 DatagramSocketImpl implementations
|
||||
* @run testng/othervm OldDatagramSocketImplTest
|
||||
*/
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
public class OldDatagramSocketImplTest {
|
||||
InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
|
||||
|
||||
@Test
|
||||
public void testOldImplConnect() {
|
||||
try (var ds = new DatagramSocket(new OldDatagramSocketImpl()) {}) {
|
||||
ds.connect(new InetSocketAddress(LOOPBACK, 6667));
|
||||
throw new RuntimeException("ERROR: test failed");
|
||||
} catch (SocketException ex) {
|
||||
assertEquals(ex.getMessage(), "connect not implemented");
|
||||
System.out.println("PASSED: default implementation of connect has thrown as expected");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOldImplConnectTwoArgs() {
|
||||
try (var ds = new DatagramSocket(new OldDatagramSocketImpl()) {}) {
|
||||
ds.connect(LOOPBACK, 6667);
|
||||
throw new RuntimeException("ERROR: test failed");
|
||||
} catch (UncheckedIOException ex) {
|
||||
assertEquals(ex.getMessage(), "connect failed");
|
||||
System.out.println("PASSED: default implementation of connect has thrown as expected");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOldImplDisconnect() {
|
||||
try (var ds = new DatagramSocket(new OldDatagramSocketImplWithValidConnect()) { }){
|
||||
ds.connect(LOOPBACK, 6667);
|
||||
ds.disconnect();
|
||||
throw new RuntimeException("ERROR: test failed");
|
||||
} catch (UncheckedIOException ex) {
|
||||
var innerException = ex.getCause();
|
||||
assertEquals(innerException.getClass(), SocketException.class);
|
||||
assertEquals(innerException.getMessage(), "disconnect not implemented");
|
||||
System.out.println("PASSED: default implementation of disconnect has thrown as expected");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOldImplPublic() {
|
||||
try (var ds = new PublicOldDatagramSocketImpl()) {
|
||||
ds.connect(LOOPBACK, 0);
|
||||
throw new RuntimeException("ERROR: test failed");
|
||||
} catch (SocketException ex) {
|
||||
assertEquals(ex.getMessage(), "connect not implemented");
|
||||
System.out.println("PASSED: default implementation of disconnect has thrown as expected");
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testOldImplPublicDisconnect() {
|
||||
try (var ds = new PublicOldDatagramSocketImplWithValidConnect()) {
|
||||
ds.disconnect();
|
||||
throw new RuntimeException("ERROR: test failed");
|
||||
} catch (UncheckedIOException ex) {
|
||||
var innerException = ex.getCause();
|
||||
assertEquals(innerException.getClass(), SocketException.class);
|
||||
assertEquals(innerException.getMessage(), "disconnect not implemented");
|
||||
System.out.println("PASSED: default implementation of disconnect has thrown as expected");
|
||||
}
|
||||
}
|
||||
|
||||
private class OldDatagramSocketImpl extends DatagramSocketImpl implements AutoCloseable {
|
||||
|
||||
@Override
|
||||
protected void create() throws SocketException { }
|
||||
|
||||
@Override
|
||||
protected void bind(int lport, InetAddress laddr) throws SocketException { }
|
||||
|
||||
@Override
|
||||
protected void send(DatagramPacket p) throws IOException { }
|
||||
|
||||
@Override
|
||||
protected int peek(InetAddress i) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int peekData(DatagramPacket p) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void receive(DatagramPacket p) throws IOException { }
|
||||
|
||||
@Override
|
||||
protected void setTimeToLive(int ttl) throws IOException { }
|
||||
|
||||
@Override
|
||||
protected int getTimeToLive() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void join(InetAddress inetaddr) throws IOException { }
|
||||
|
||||
@Override
|
||||
protected void leave(InetAddress inetaddr) throws IOException { }
|
||||
|
||||
@Override
|
||||
protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException { }
|
||||
|
||||
@Override
|
||||
protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException { }
|
||||
|
||||
@Override
|
||||
public void close() { }
|
||||
|
||||
@Override
|
||||
public void setOption(int optID, Object value) throws SocketException { }
|
||||
|
||||
@Override
|
||||
public Object getOption(int optID) throws SocketException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class OldDatagramSocketImplWithValidConnect extends OldDatagramSocketImpl implements AutoCloseable {
|
||||
@Override
|
||||
protected void connect(InetAddress address, int port) throws SocketException { }
|
||||
}
|
||||
// Overriding connect() to make it public so that it can be called
|
||||
// directly from the test code
|
||||
private class PublicOldDatagramSocketImpl extends OldDatagramSocketImpl {
|
||||
public void connect(InetAddress addr, int port) throws SocketException { super.connect(addr, port); }
|
||||
}
|
||||
// Overriding disconnect() to make it public so that it can be called
|
||||
// directly from the test code
|
||||
private class PublicOldDatagramSocketImplWithValidConnect extends OldDatagramSocketImplWithValidConnect {
|
||||
public void disconnect() { super.disconnect(); }
|
||||
}
|
||||
}
|
||||
188
test/jdk/java/net/DatagramSocket/PortUnreachable.java
Normal file
188
test/jdk/java/net/DatagramSocket/PortUnreachable.java
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2020, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4361783
|
||||
* @key intermittent
|
||||
* @summary Test to see if ICMP Port Unreachable on non-connected
|
||||
* DatagramSocket causes a SocketException "socket closed"
|
||||
* exception on Windows 2000.
|
||||
* @run main/othervm PortUnreachable
|
||||
*/
|
||||
|
||||
import java.net.BindException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class PortUnreachable {
|
||||
|
||||
DatagramSocket clientSock;
|
||||
int serverPort;
|
||||
int clientPort;
|
||||
|
||||
public void serverSend() throws Exception {
|
||||
InetAddress addr = InetAddress.getLocalHost();
|
||||
Thread.sleep(1000);
|
||||
// send a delayed packet which should mean a delayed icmp
|
||||
// port unreachable
|
||||
byte b[] = "A late msg".getBytes();
|
||||
DatagramPacket packet = new DatagramPacket(b, b.length, addr,
|
||||
serverPort);
|
||||
clientSock.send(packet);
|
||||
|
||||
DatagramSocket sock = recreateServerSocket(serverPort);
|
||||
b = "Greetings from the server".getBytes();
|
||||
packet = new DatagramPacket(b, b.length, addr, clientPort);
|
||||
sock.send(packet);
|
||||
Thread.sleep(500); // give time to the kernel to send packet
|
||||
sock.close();
|
||||
}
|
||||
|
||||
DatagramSocket recreateServerSocket (int serverPort) throws Exception {
|
||||
DatagramSocket serverSocket = null;
|
||||
int retryCount = 0;
|
||||
long sleeptime = 0;
|
||||
System.out.println("Attempting to recreate server socket with port: " +
|
||||
serverPort);
|
||||
// it's possible that this method intermittently fails, if some other
|
||||
// process running on the machine grabs the port we want before us,
|
||||
// and doesn't release it before the 10 * 500 ms are elapsed...
|
||||
while (serverSocket == null) {
|
||||
try {
|
||||
serverSocket = new DatagramSocket(serverPort, InetAddress.getLocalHost());
|
||||
} catch (BindException bEx) {
|
||||
if (retryCount++ < 10) {
|
||||
sleeptime += sleepAtLeast(500);
|
||||
} else {
|
||||
System.out.println("Give up after 10 retries and " + sleeptime(sleeptime));
|
||||
System.out.println("Has some other process grabbed port " + serverPort + "?");
|
||||
throw bEx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("PortUnreachableTest.recreateServerSocket: returning socket == "
|
||||
+ serverSocket.getLocalAddress() + ":" + serverSocket.getLocalPort()
|
||||
+ " obtained at " + attempt(retryCount) + " attempt with " + sleeptime(sleeptime));
|
||||
return serverSocket;
|
||||
}
|
||||
|
||||
long sleepAtLeast(long millis) throws Exception {
|
||||
long start = System.nanoTime();
|
||||
long ms = millis;
|
||||
while (ms > 0) {
|
||||
assert ms < Long.MAX_VALUE/1000_000L;
|
||||
Thread.sleep(ms);
|
||||
long elapsedms = (System.nanoTime() - start)/1000_000L;
|
||||
ms = millis - elapsedms;
|
||||
}
|
||||
return millis - ms;
|
||||
}
|
||||
|
||||
String attempt(int retry) {
|
||||
switch (retry) {
|
||||
case 0: return "first";
|
||||
case 1: return "second";
|
||||
case 2: return "third";
|
||||
default: return retry + "th";
|
||||
}
|
||||
}
|
||||
|
||||
String sleeptime(long millis) {
|
||||
if (millis == 0) return "no sleep";
|
||||
long sec = millis / 1000L;
|
||||
long ms = millis % 1000L;
|
||||
String sleeptime = "";
|
||||
if (millis > 0) {
|
||||
if (sec > 0) {
|
||||
sleeptime = "" + sec + " s" +
|
||||
(ms > 0 ? " " : "");
|
||||
}
|
||||
if (ms > 0 ) {
|
||||
sleeptime += ms + " ms";
|
||||
}
|
||||
} else sleeptime = millis + " ms"; // should not happen
|
||||
return sleeptime + " of sleep time";
|
||||
}
|
||||
|
||||
PortUnreachable() throws Exception {
|
||||
clientSock = new DatagramSocket(new InetSocketAddress(InetAddress.getLocalHost(), 0));
|
||||
clientPort = clientSock.getLocalPort();
|
||||
|
||||
}
|
||||
|
||||
void execute () throws Exception{
|
||||
|
||||
// pick a port for the server
|
||||
DatagramSocket sock2 = new DatagramSocket(new InetSocketAddress(InetAddress.getLocalHost(), 0));
|
||||
serverPort = sock2.getLocalPort();
|
||||
|
||||
// send a burst of packets to the unbound port - we should get back
|
||||
// icmp port unreachable messages
|
||||
//
|
||||
InetAddress addr = InetAddress.getLocalHost();
|
||||
byte b[] = "Hello me".getBytes();
|
||||
DatagramPacket packet = new DatagramPacket(b, b.length, addr,
|
||||
serverPort);
|
||||
//close just before sending
|
||||
sock2.close();
|
||||
for (int i=0; i<100; i++)
|
||||
clientSock.send(packet);
|
||||
|
||||
serverSend();
|
||||
|
||||
// try to receive
|
||||
b = new byte[25];
|
||||
packet = new DatagramPacket(b, b.length, addr, serverPort);
|
||||
clientSock.setSoTimeout(10000);
|
||||
clientSock.receive(packet);
|
||||
System.out.println("client received data packet " + new String(packet.getData()));
|
||||
|
||||
// done
|
||||
clientSock.close();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// A BindException might be thrown intermittently. In that case retry
|
||||
// 3 times before propagating the exception to finish execution.
|
||||
int catchCount = 0;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
PortUnreachable test = new PortUnreachable();
|
||||
test.execute();
|
||||
return;
|
||||
} catch (BindException bEx) {
|
||||
System.out.println("Failed to bind server: " + bEx);
|
||||
if (++catchCount > 3) {
|
||||
System.out.printf("Max retry count exceeded (%d)%n", catchCount);
|
||||
throw bEx;
|
||||
}
|
||||
System.out.printf("Retrying; retry count: %d%n", catchCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
test/jdk/java/net/DatagramSocket/ReportSocketClosed.java
Normal file
58
test/jdk/java/net/DatagramSocket/ReportSocketClosed.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2018, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4190513
|
||||
* @summary Make sure operating on a closed
|
||||
* DatagramSocket throws the appropriate exception
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
public class ReportSocketClosed {
|
||||
public static void main(String[] args) throws Exception {
|
||||
DatagramSocket soc;
|
||||
InetAddress sin = null;
|
||||
byte[] array = {21,22,23};
|
||||
|
||||
try {
|
||||
soc = new DatagramSocket(0);
|
||||
sin = InetAddress.getLocalHost();
|
||||
soc.close();
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Got unexpected exception" + e);
|
||||
}
|
||||
|
||||
try {
|
||||
soc.receive(new DatagramPacket(array, array.length));
|
||||
} catch (Exception e2) {
|
||||
// We expect a SocketException here.
|
||||
// If we get any other exceptions, the test fails.
|
||||
if (e2 instanceof SocketException)
|
||||
return;
|
||||
else
|
||||
throw e2;
|
||||
}
|
||||
}
|
||||
}
|
||||
471
test/jdk/java/net/DatagramSocket/ReuseAddressTest.java
Normal file
471
test/jdk/java/net/DatagramSocket/ReuseAddressTest.java
Normal file
|
|
@ -0,0 +1,471 @@
|
|||
/* Copyright (c) 2016, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketException;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8153674
|
||||
* @key intermittent
|
||||
* @summary This test might fail intermittently as it needs a UDP socket that
|
||||
* binds to the wildcard address.
|
||||
* @summary Expected SocketException not thrown when calling bind() with
|
||||
* setReuseAddress(false)
|
||||
* @run main/othervm ReuseAddressTest
|
||||
*/
|
||||
|
||||
public class ReuseAddressTest {
|
||||
|
||||
String getInfo(DatagramSocket soc) {
|
||||
if (soc == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return "localPort: " + soc.getLocalPort()
|
||||
+ "; localAddress: " + soc.getLocalAddress()
|
||||
+ "; remotePort: " + soc.getPort()
|
||||
+ "; remoteAddress: " + soc.getInetAddress()
|
||||
+ "; isClosed: " + soc.isClosed()
|
||||
+ "; isBound: " + soc.isBound();
|
||||
}
|
||||
|
||||
static InetSocketAddress createSocketAddress(int testMcastPort) throws Exception {
|
||||
InetAddress localAddress = InetAddress.getLocalHost();
|
||||
InetSocketAddress localSocketAddress = new InetSocketAddress(localAddress, testMcastPort);
|
||||
return localSocketAddress;
|
||||
}
|
||||
|
||||
/* standalone interface */
|
||||
public static void main(String argv[]) throws Exception {
|
||||
ReuseAddressTest test = new ReuseAddressTest();
|
||||
test.DatagramSocket0029();
|
||||
test.DatagramSocket0030();
|
||||
test.DatagramSocket0031();
|
||||
test.DatagramSocket0032();
|
||||
test.DatagramSocket0034();
|
||||
test.DatagramSocket0035();
|
||||
test.DatagramSocket2028();
|
||||
test.DatagramSocket2029();
|
||||
test.DatagramSocket2030();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalence class partitioning with input values orientation for public
|
||||
* void setReuseAddress(boolean on) throws SocketException,
|
||||
* <br><b>on</b>: false.
|
||||
* <br><b>Expected results</b>: getReuseAddress() will return false
|
||||
*/
|
||||
public void DatagramSocket0029() throws Exception {
|
||||
String testCaseID = "DatagramSocket0029";
|
||||
System.out.println(" >> " + testCaseID + ": " + "public void setReuseAddress(boolean on) throws SocketException");
|
||||
|
||||
DatagramSocket ds = null;
|
||||
try {
|
||||
ds = new DatagramSocket(null);
|
||||
ds.setReuseAddress(false);
|
||||
if (ds.getReuseAddress() == true) {
|
||||
throw new RuntimeException("SO_REUSEADDR is not set to false");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("unexpected: " + e);
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Security restriction");
|
||||
} finally {
|
||||
if (ds != null) {
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OKAY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalence class partitioning with input values orientation for public
|
||||
* void setReuseAddress(boolean on) throws SocketException,
|
||||
* <br><b>on</b>: true.
|
||||
* <br><b>Expected results</b>: Allows completely duplicate bindings (same
|
||||
* address and port) on multicast sockets
|
||||
*/
|
||||
public void DatagramSocket0030() throws Exception {
|
||||
String testCaseID = "DatagramSocket0030";
|
||||
System.out.println(" >> " + testCaseID + ": " + "public void setReuseAddress(boolean on) throws SocketException");
|
||||
|
||||
MulticastSocket ms1 = null;
|
||||
MulticastSocket ms2 = null;
|
||||
try {
|
||||
InetSocketAddress addr = createSocketAddress(0);
|
||||
|
||||
ms1 = new MulticastSocket(null);
|
||||
ms1.setReuseAddress(true);
|
||||
if (!ms1.getReuseAddress()) {
|
||||
System.out.println("Cannot check: "
|
||||
+ " safety for SO_REUSEADDR option is not guaranteed");
|
||||
}
|
||||
|
||||
try {
|
||||
ms1.bind(addr);
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException("cannot bind first socket to " + addr
|
||||
+ " unexpected " + e);
|
||||
}
|
||||
|
||||
addr = createSocketAddress(ms1.getLocalPort());
|
||||
ms2 = new MulticastSocket(null);
|
||||
ms2.setReuseAddress(true);
|
||||
if (!ms2.getReuseAddress()) {
|
||||
System.out.println("Cannot check: "
|
||||
+ " safety for SO_REUSEADDR option is not guaranteed");
|
||||
}
|
||||
|
||||
try {
|
||||
ms2.bind(addr);
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException("cannot bind second socket to " + addr
|
||||
+ " unexpected " + e);
|
||||
}
|
||||
|
||||
if (ms1.getLocalPort() != addr.getPort() || !ms1.isBound()
|
||||
|| ms2.getLocalPort() != addr.getPort() || !ms2.isBound()) {
|
||||
System.out.println("bind() fails with: " + addr);
|
||||
System.out.println(" ms1 [" + getInfo(ms1) + "]");
|
||||
System.out.println(" ms2 [" + getInfo(ms2) + "]");
|
||||
System.out.println(" getReuseAddress(): " + ms2.getReuseAddress());
|
||||
throw new RuntimeException("bind() fails with: " + addr);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("unexpected: " + e);
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Security restriction");
|
||||
} finally {
|
||||
if (ms1 != null) {
|
||||
ms1.close();
|
||||
}
|
||||
if (ms2 != null) {
|
||||
ms2.close();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OKAY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalence class partitioning with input values orientation for public
|
||||
* void setReuseAddress(boolean on) throws SocketException,
|
||||
* <br><b>on</b>: false.
|
||||
* <br><b>Expected results</b>: The second bind will throw SocketException,
|
||||
* when SO_REUSEADDR disable
|
||||
*/
|
||||
public void DatagramSocket0031() throws Exception {
|
||||
String testCaseID = "DatagramSocket0031";
|
||||
System.out.println(" >> " + testCaseID + ": " + "public void setReuseAddress(boolean on) throws SocketException");
|
||||
|
||||
MulticastSocket ms1 = null;
|
||||
MulticastSocket ms2 = null;
|
||||
try {
|
||||
InetSocketAddress addr = createSocketAddress(0);
|
||||
|
||||
ms1 = new MulticastSocket(null);
|
||||
try {
|
||||
ms1.bind(addr);
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException("cannot bind first socket to " + addr
|
||||
+ " unexpected " + e);
|
||||
}
|
||||
|
||||
addr = createSocketAddress(ms1.getLocalPort());
|
||||
ms2 = new MulticastSocket(null);
|
||||
ms2.setReuseAddress(false); // method under test
|
||||
|
||||
try {
|
||||
ms2.bind(addr);
|
||||
System.out.println("No exceptions: ");
|
||||
System.out.println(" addr: " + addr);
|
||||
System.out.println(" ms1 [" + getInfo(ms1) + "]");
|
||||
System.out.println(" ms2 [" + getInfo(ms2) + "]");
|
||||
System.out.println(" getReuseAddress(): " + ms2.getReuseAddress());
|
||||
throw new RuntimeException("no exceptions from bind() with " + addr);
|
||||
} catch (SocketException e) {
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("unexpected: " + e);
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Security restriction");
|
||||
} finally {
|
||||
if (ms1 != null) {
|
||||
ms1.close();
|
||||
}
|
||||
if (ms2 != null) {
|
||||
ms2.close();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OKAY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalence class partitioning with input values orientation for public
|
||||
* void setReuseAddress(boolean on) throws SocketException,
|
||||
* <br><b>on</b>: true.
|
||||
* <br><b>Expected results</b>: Allows a single process to bind the same
|
||||
* port to multiple sockets as long as each bind specifies a different local
|
||||
* IP address
|
||||
*/
|
||||
public void DatagramSocket0032() throws Exception {
|
||||
String testCaseID = "DatagramSocket0032";
|
||||
System.out.println(" >> " + testCaseID + ": " + "public void setReuseAddress(boolean on) throws SocketException");
|
||||
|
||||
DatagramSocket ds1 = null;
|
||||
DatagramSocket ds2 = null;
|
||||
try {
|
||||
|
||||
InetSocketAddress isa1 = createSocketAddress(0);
|
||||
InetAddress addr = isa1.getAddress();
|
||||
InetAddress wildcard = InetAddress.getByName("0.0.0.0");
|
||||
if (addr.equals(wildcard) || addr.isLoopbackAddress()) {
|
||||
System.out.println("Cannot check: addresses are equal");
|
||||
}
|
||||
|
||||
|
||||
ds1 = new DatagramSocket(null);
|
||||
ds1.setReuseAddress(true); // method under test
|
||||
if (!ds1.getReuseAddress()) {
|
||||
System.out.println("Cannot check: "
|
||||
+ " safety for SO_REUSEADDR option is not guaranteed");
|
||||
}
|
||||
ds1.bind(isa1);
|
||||
|
||||
InetSocketAddress isa2 = new InetSocketAddress(wildcard, ds1.getLocalPort());
|
||||
|
||||
ds2 = new DatagramSocket(null);
|
||||
ds2.setReuseAddress(true); // method under test
|
||||
if (!ds2.getReuseAddress()) {
|
||||
System.out.println("Cannot check: "
|
||||
+ " safety for SO_REUSEADDR option is not guaranteed");
|
||||
}
|
||||
|
||||
try {
|
||||
ds2.bind(isa2);
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException("cannot bind second socket to " + isa2
|
||||
+ " unexpected " + e);
|
||||
}
|
||||
|
||||
if (ds1.getLocalPort() != ds2.getLocalPort() || !ds1.isBound()
|
||||
|| !ds2.isBound()) {
|
||||
System.out.println("bind() fails with: " + addr);
|
||||
System.out.println(" ds1 [" + getInfo(ds1) + "]");
|
||||
System.out.println(" ds2 [" + getInfo(ds2) + "]");
|
||||
System.out.println(" getReuseAddress(): " + ds2.getReuseAddress());
|
||||
throw new RuntimeException("bind() fails with: " + addr);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("unexpected: " + e);
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Security restriction");
|
||||
} finally {
|
||||
if (ds1 != null) {
|
||||
ds1.close();
|
||||
}
|
||||
if (ds2 != null) {
|
||||
ds2.close();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OKAY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertion testing for public int getTrafficClass() throws
|
||||
* SocketException, will return a number in range from 0 to 255 or throw
|
||||
* SocketException.
|
||||
*/
|
||||
public void DatagramSocket2028() throws Exception {
|
||||
String testCaseID = "DatagramSocket2028";
|
||||
System.out.println(" >> " + testCaseID + ": " + "public int getTrafficClass() throws SocketException");
|
||||
|
||||
DatagramSocket ds = null;
|
||||
try {
|
||||
ds = new DatagramSocket();
|
||||
int tc = ds.getTrafficClass();
|
||||
if (tc < 0 || tc > 255) {
|
||||
throw new RuntimeException("getTrafficClass() returns: " + tc);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Security restriction: " + e);
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("Unexpected exception : " + e);
|
||||
} finally {
|
||||
if (ds != null) {
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OKAY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertion testing for public void setTrafficClass(int tc) throws
|
||||
* SocketException, IAE will be thrown with tc less than 0 or greater than
|
||||
* 255.
|
||||
*/
|
||||
public void DatagramSocket2029() throws Exception {
|
||||
String testCaseID = "DatagramSocket2029";
|
||||
System.out.println(" >> " + testCaseID + ": " + "public void setTrafficClass(int tc) throws SocketException");
|
||||
|
||||
DatagramSocket ds = null;
|
||||
try {
|
||||
ds = new DatagramSocket();
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Security restriction: " + e);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("cannot create socket: " + e);
|
||||
}
|
||||
|
||||
int[] values = {
|
||||
Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -1000, -2, -1,
|
||||
256, 257, 1000, 50000, Integer.MAX_VALUE - 1, Integer.MAX_VALUE
|
||||
};
|
||||
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
try {
|
||||
ds.setTrafficClass(values[i]);
|
||||
System.out.println("No exception with: " + values[i]);
|
||||
System.out.println("getTrafficClass() returns: " + ds.getTrafficClass());
|
||||
ds.close();
|
||||
throw new RuntimeException("setTrafficClass() fails with : " + values[i]);
|
||||
} catch (SocketException e) {
|
||||
ds.close();
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("setTrafficClass() throws : " + e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OKAY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertion testing for public void setTrafficClass(int tc) throws
|
||||
* SocketException, only SocketException may be thrown with tc in range from
|
||||
* 0 to 255.
|
||||
*/
|
||||
public void DatagramSocket2030() throws Exception {
|
||||
String testCaseID = "DatagramSocket2030";
|
||||
System.out.println(" >> " + testCaseID + ": " + "public void setTrafficClass(int tc) throws SocketException");
|
||||
|
||||
DatagramSocket ds = null;
|
||||
try {
|
||||
ds = new DatagramSocket();
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Security restriction: " + e);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("cannot create socket: " + e);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 255; i++) {
|
||||
try {
|
||||
ds.setTrafficClass(i);
|
||||
} catch (SocketException e) {
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OKAY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalence class partitioning with input values orientation for public
|
||||
* void setBroadcast(boolean on) throws SocketException,
|
||||
* <br><b>on</b>: false.
|
||||
* <br><b>Expected results</b>: getBroadcast() will return false
|
||||
*/
|
||||
public void DatagramSocket0034() throws Exception {
|
||||
String testCaseID = "DatagramSocket0034";
|
||||
System.out.println(" >> " + testCaseID + ": " + "public void setBroadcast(boolean on) throws SocketException");
|
||||
|
||||
DatagramSocket ds = null;
|
||||
try {
|
||||
ds = new DatagramSocket();
|
||||
ds.setBroadcast(false);
|
||||
if (ds.getBroadcast() == true) {
|
||||
throw new RuntimeException("SO_BROADCAST is not set to false");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("unexpected: " + e);
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Security restriction");
|
||||
} finally {
|
||||
if (ds != null) {
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OKAY");
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalence class partitioning with input values orientation for public
|
||||
* void setBroadcast(boolean on) throws SocketException,
|
||||
* <br><b>on</b>: true.
|
||||
* <br><b>Expected results</b>: getBroadcast() will return true
|
||||
*/
|
||||
public void DatagramSocket0035() throws Exception {
|
||||
String testCaseID = "DatagramSocket0035";
|
||||
System.out.println(" >> " + testCaseID + ": " + "public void setBroadcast(boolean on) throws SocketException");
|
||||
|
||||
DatagramSocket ds = null;
|
||||
try {
|
||||
ds = new DatagramSocket();
|
||||
ds.setBroadcast(true);
|
||||
if (ds.getBroadcast() == false) {
|
||||
throw new RuntimeException("SO_BROADCAST is not set to true");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.out);
|
||||
throw new RuntimeException("unexpected: " + e);
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Security restriction");
|
||||
} finally {
|
||||
if (ds != null) {
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OKAY");
|
||||
}
|
||||
}
|
||||
87
test/jdk/java/net/DatagramSocket/Send12k.java
Normal file
87
test/jdk/java/net/DatagramSocket/Send12k.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4094894
|
||||
* @summary On W95/W98 it's not possible to send a datagram >12k
|
||||
* via the loopback address.
|
||||
* @run main Send12k
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true Send12k
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
|
||||
public class Send12k {
|
||||
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
|
||||
int SEND_SIZE=0;
|
||||
|
||||
if(System.getProperty("os.name").contains("Mac")) {
|
||||
SEND_SIZE = 16 * 576;
|
||||
} else {
|
||||
SEND_SIZE = 16 * 1024;
|
||||
}
|
||||
InetAddress localHost = InetAddress.getLocalHost();
|
||||
DatagramSocket s1 = new DatagramSocket();
|
||||
DatagramSocket s2 = new DatagramSocket(0, localHost);
|
||||
|
||||
byte b1[] = new byte[ SEND_SIZE ];
|
||||
DatagramPacket p1 = new DatagramPacket(b1, 0, b1.length,
|
||||
localHost,
|
||||
s2.getLocalPort());
|
||||
boolean sendOkay = true;
|
||||
try {
|
||||
System.out.println("Sending to: [" + localHost + "]:" + s2.getLocalPort());
|
||||
s1.send(p1);
|
||||
} catch (IOException e) {
|
||||
/*
|
||||
* Prior to merlin a send of > 12k to loopback address
|
||||
* would fail silently.
|
||||
*/
|
||||
System.out.println("Sending failed: " + e);
|
||||
sendOkay = false;
|
||||
}
|
||||
|
||||
if (sendOkay) {
|
||||
byte b2[] = new byte[ SEND_SIZE * 2];
|
||||
DatagramPacket p2 = new DatagramPacket( b2, SEND_SIZE * 2 );
|
||||
s2.setSoTimeout(2000);
|
||||
|
||||
try {
|
||||
s2.receive(p1);
|
||||
} catch (InterruptedIOException ioe) {
|
||||
throw new Exception("Datagram not received within timeout");
|
||||
}
|
||||
|
||||
if (p1.getLength() != SEND_SIZE) {
|
||||
throw new Exception("Received datagram incorrect size");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
232
test/jdk/java/net/DatagramSocket/SendCheck.java
Normal file
232
test/jdk/java/net/DatagramSocket/SendCheck.java
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8236105
|
||||
* @summary Check that DatagramSocket, MulticastSocket,
|
||||
* DatagramSocketAdaptor and DatagramChannel all
|
||||
* throw expected Exception when passed a DatagramPacket
|
||||
* with invalid details
|
||||
* @run testng SendCheck
|
||||
*/
|
||||
|
||||
public class SendCheck {
|
||||
private InetAddress loopbackAddr, wildcardAddr;
|
||||
static final Class<IOException> IOE = IOException.class;
|
||||
static final Class<SocketException> SE = SocketException.class;
|
||||
|
||||
static final byte[] buf = {0, 1, 2};
|
||||
static DatagramSocket socket;
|
||||
|
||||
@BeforeTest
|
||||
public void setUp() {
|
||||
try {
|
||||
socket = new DatagramSocket();
|
||||
} catch (Exception e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void closeDown() {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
static final class Packet {
|
||||
private Packet(String description, DatagramPacket packet) {
|
||||
this.description = description;
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
final String description;
|
||||
final DatagramPacket packet;
|
||||
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public static Packet of(DatagramPacket packet) {
|
||||
InetAddress address = packet.getAddress();
|
||||
int port = packet.getPort();
|
||||
String description;
|
||||
if (address == null) {
|
||||
description = "<null>:" + port;
|
||||
} else if (port < 0) {
|
||||
description = packet.getAddress().toString() + ":" + port;
|
||||
} else {
|
||||
description = packet.getSocketAddress().toString();
|
||||
}
|
||||
return new Packet(description, packet);
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider(name = "packets")
|
||||
Object[][] providerIO() throws IOException {
|
||||
loopbackAddr = InetAddress.getLoopbackAddress();
|
||||
wildcardAddr = new InetSocketAddress(0).getAddress();
|
||||
|
||||
// loopback addr with no port set
|
||||
var pkt1 = new DatagramPacket(buf, 0, buf.length);
|
||||
pkt1.setAddress(loopbackAddr);
|
||||
|
||||
// wildcard addr with no port set
|
||||
var pkt2 = new DatagramPacket(buf, 0, buf.length);
|
||||
pkt2.setAddress(wildcardAddr);
|
||||
|
||||
/*
|
||||
Commented until JDK-8236807 is fixed
|
||||
|
||||
// wildcard addr w/valid port
|
||||
var pkt3 = new DatagramPacket(buf, 0, buf.length);
|
||||
pkt3.setAddress(wildcardAddr);
|
||||
pkt3.setPort(socket.getLocalPort());
|
||||
*/
|
||||
|
||||
List<Packet> Packets = List.of(Packet.of(pkt1), Packet.of(pkt2));
|
||||
|
||||
List<Sender> senders = List.of(
|
||||
Sender.of(new DatagramSocket(null)),
|
||||
Sender.of(new MulticastSocket(null)),
|
||||
Sender.of(DatagramChannel.open()),
|
||||
Sender.of(DatagramChannel.open().socket())
|
||||
);
|
||||
|
||||
List<Object[]> testcases = new ArrayList<>();
|
||||
for (var packet : Packets) {
|
||||
addTestCaseFor(testcases, senders, packet);
|
||||
}
|
||||
|
||||
return testcases.toArray(new Object[0][0]);
|
||||
}
|
||||
|
||||
static void addTestCaseFor(List<Object[]> testcases,
|
||||
List<Sender> senders, Packet p) {
|
||||
for (var s : senders) {
|
||||
Object[] testcase = new Object[]{s, p, s.expectedException()};
|
||||
testcases.add(testcase);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "packets")
|
||||
public static void sendCheck(Sender<IOException> sender,
|
||||
Packet packet,
|
||||
Class<? extends Throwable> exception) {
|
||||
DatagramPacket pkt = packet.packet;
|
||||
if (exception != null) {
|
||||
Throwable t = expectThrows(exception, () -> sender.send(pkt));
|
||||
System.out.printf("%s got expected exception %s%n",
|
||||
packet.toString(), t);
|
||||
} else {
|
||||
try {
|
||||
sender.send(pkt);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError("Unexpected exception for "
|
||||
+ sender + " / " + packet, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Sender<E extends Exception> extends AutoCloseable {
|
||||
void send(DatagramPacket p) throws E;
|
||||
|
||||
void close() throws E;
|
||||
|
||||
Class<? extends E> expectedException();
|
||||
|
||||
static Sender<IOException> of(DatagramSocket socket) {
|
||||
return new SenderImpl<>(socket, socket::send, socket::close, SE);
|
||||
}
|
||||
|
||||
static Sender<IOException> of(DatagramChannel socket) {
|
||||
SenderImpl.Send<IOException> send =
|
||||
(pkt) -> socket.send(ByteBuffer.wrap(pkt.getData()),
|
||||
pkt.getSocketAddress());
|
||||
return new SenderImpl<>(socket, send, socket::close, SE);
|
||||
}
|
||||
}
|
||||
|
||||
static final class SenderImpl<E extends Exception> implements Sender<E> {
|
||||
@FunctionalInterface
|
||||
interface Send<E extends Exception> {
|
||||
void send(DatagramPacket p) throws E;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface Closer<E extends Exception> {
|
||||
void close() throws E;
|
||||
}
|
||||
|
||||
private final Send<E> send;
|
||||
private final Closer<E> closer;
|
||||
private final Object socket;
|
||||
private final Class<? extends E> expectedException;
|
||||
|
||||
public SenderImpl(Object socket, Send<E> send, Closer<E> closer,
|
||||
Class<? extends E> expectedException) {
|
||||
this.socket = socket;
|
||||
this.send = send;
|
||||
this.closer = closer;
|
||||
this.expectedException = expectedException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(DatagramPacket p) throws E {
|
||||
send.send(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws E {
|
||||
closer.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends E> expectedException() {
|
||||
return expectedException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return socket.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
}
|
||||
193
test/jdk/java/net/DatagramSocket/SendDatagramToBadAddress.java
Normal file
193
test/jdk/java/net/DatagramSocket/SendDatagramToBadAddress.java
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2022, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
*
|
||||
* @bug 4204320
|
||||
*
|
||||
* @summary DatagramSocket.send should throw exception when connected
|
||||
* to an invalid destination (on platforms that support it).
|
||||
* @run main/othervm SendDatagramToBadAddress -d
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.io.InterruptedIOException;
|
||||
|
||||
public class SendDatagramToBadAddress {
|
||||
|
||||
static boolean debug = false;
|
||||
|
||||
public static boolean OSsupportsFeature () {
|
||||
Properties p = System.getProperties ();
|
||||
String v;
|
||||
if (p.getProperty ("os.name").equals ("Windows 2000"))
|
||||
return (true);
|
||||
if (p.getProperty ("os.name").equals ("Linux"))
|
||||
return (true);
|
||||
if (p.getProperty ("os.name").startsWith ("Mac OS"))
|
||||
return (true);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void print (String s) {
|
||||
if (debug)
|
||||
System.out.println (s);
|
||||
}
|
||||
|
||||
class Server {
|
||||
|
||||
DatagramSocket server;
|
||||
byte[] buf = new byte [128];
|
||||
DatagramPacket pack = new DatagramPacket (buf, buf.length);
|
||||
|
||||
public Server (DatagramSocket s) {
|
||||
server = s;
|
||||
}
|
||||
|
||||
public void receive (int loop, boolean expectError) throws Exception {
|
||||
for (int i=0; i<loop; i++) {
|
||||
try {
|
||||
server.receive (pack);
|
||||
print("received data from address " + pack.getAddress()
|
||||
+ " port " + pack.getPort());
|
||||
} catch (Exception e) {
|
||||
if (expectError) {
|
||||
print ("Got expected error: " + e);
|
||||
continue;
|
||||
} else {
|
||||
print ("Got: " + new String (pack.getData()));
|
||||
print ("Expected: " + new String (buf));
|
||||
throw new Exception ("Error reading data: Iter " +i);
|
||||
}
|
||||
}
|
||||
String s1 = "Hello, server"+i;
|
||||
byte[] buf = s1.getBytes();
|
||||
if (!s1.equals (new String (pack.getData(),
|
||||
pack.getOffset(),pack.getLength()))) {
|
||||
print ("Got: " + new String (pack.getData()));
|
||||
print ("Expected: " + new String (buf));
|
||||
throw new Exception ("Error comparing data: Iter " +i);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static void main (String args[]) throws Exception {
|
||||
if (args.length >=1 && args[0].equals ("-d")) {
|
||||
debug = true;
|
||||
}
|
||||
SendDatagramToBadAddress ud = new SendDatagramToBadAddress ();
|
||||
ud.run ();
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
if (OSsupportsFeature()) {
|
||||
print ("running on OS that supports ICMP port unreachable");
|
||||
}
|
||||
try (DatagramSocket sock = new DatagramSocket()) {
|
||||
test(sock);
|
||||
}
|
||||
}
|
||||
|
||||
private void test(DatagramSocket sock) throws Exception {
|
||||
print("Testing with " + sock.getClass());
|
||||
InetAddress addr = InetAddress.getLoopbackAddress();
|
||||
DatagramSocket serversock = new DatagramSocket(0);
|
||||
DatagramPacket p;
|
||||
byte[] buf;
|
||||
int port = serversock.getLocalPort ();
|
||||
print("tests will be run against destination address " + addr + " port " + port);
|
||||
final int loop = 5;
|
||||
Server s = new Server (serversock);
|
||||
int i;
|
||||
|
||||
print ("Checking send to connected address ...");
|
||||
sock.connect(addr, port);
|
||||
print("socket is locally bound to address " + sock.getLocalAddress()
|
||||
+ " port " + sock.getLocalPort());
|
||||
|
||||
for (i = 0; i < loop; i++) {
|
||||
try {
|
||||
buf = ("Hello, server"+i).getBytes();
|
||||
if (i % 2 == 1)
|
||||
p = new DatagramPacket(buf, buf.length, addr, port);
|
||||
else
|
||||
p = new DatagramPacket(buf, buf.length);
|
||||
sock.send(p);
|
||||
} catch (Exception ex) {
|
||||
print ("Got unexpected exception: " + ex);
|
||||
throw new Exception ("Error sending data: ");
|
||||
}
|
||||
}
|
||||
|
||||
s.receive (loop, false);
|
||||
|
||||
// check disconnect() works
|
||||
|
||||
print ("Checking send to non-connected address ...");
|
||||
sock.disconnect ();
|
||||
buf = ("Hello, server"+0).getBytes();
|
||||
p = new DatagramPacket(buf, buf.length, addr, port);
|
||||
sock.send (p);
|
||||
s.receive (1, false);
|
||||
|
||||
// check send() to invalid destination followed by a blocking receive
|
||||
// returns an error
|
||||
|
||||
print ("Checking send to invalid address ...");
|
||||
sock.connect(addr, port);
|
||||
serversock.close ();
|
||||
try {
|
||||
sock.setSoTimeout (4000);
|
||||
} catch (Exception e) {
|
||||
print ("could not set timeout");
|
||||
throw e;
|
||||
}
|
||||
|
||||
boolean goterror = false;
|
||||
|
||||
for (i = 0; i < loop; i++) {
|
||||
try {
|
||||
buf = ("Hello, server"+i).getBytes();
|
||||
p = new DatagramPacket(buf, buf.length, addr, port);
|
||||
sock.send(p);
|
||||
p = new DatagramPacket(buf, buf.length, addr, port);
|
||||
sock.receive (p);
|
||||
print("(unexpectedly) received data from address " + p.getAddress()
|
||||
+ " port " + p.getPort() + " on attempt " + i);
|
||||
} catch (InterruptedIOException ex) {
|
||||
print ("socket timeout");
|
||||
} catch (Exception ex) {
|
||||
print ("Got expected exception: " + ex);
|
||||
goterror = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!goterror && OSsupportsFeature ()) {
|
||||
print ("Didnt get expected exception: ");
|
||||
throw new Exception ("send did not return expected error");
|
||||
}
|
||||
}
|
||||
}
|
||||
109
test/jdk/java/net/DatagramSocket/SendPortZero.java
Normal file
109
test/jdk/java/net/DatagramSocket/SendPortZero.java
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2024, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8236105 8240533
|
||||
* @summary Check that DatagramSocket throws expected
|
||||
* Exception when sending a DatagramPacket with port 0
|
||||
* @run testng/othervm SendPortZero
|
||||
*/
|
||||
|
||||
public class SendPortZero {
|
||||
private InetAddress loopbackAddr, wildcardAddr;
|
||||
private DatagramSocket datagramSocket, datagramSocketAdaptor;
|
||||
private DatagramPacket loopbackZeroPkt, wildcardZeroPkt, wildcardValidPkt;
|
||||
|
||||
private static final Class<SocketException> SE = SocketException.class;
|
||||
|
||||
@BeforeTest
|
||||
public void setUp() throws IOException {
|
||||
datagramSocket = new DatagramSocket();
|
||||
datagramSocketAdaptor = DatagramChannel.open().socket();
|
||||
|
||||
byte[] buf = "test".getBytes();
|
||||
|
||||
// Addresses
|
||||
loopbackAddr = InetAddress.getLoopbackAddress();
|
||||
wildcardAddr = new InetSocketAddress(0).getAddress();
|
||||
|
||||
// Packets
|
||||
// loopback w/port 0
|
||||
loopbackZeroPkt = new DatagramPacket(buf, 0, buf.length);
|
||||
loopbackZeroPkt.setAddress(loopbackAddr);
|
||||
loopbackZeroPkt.setPort(0);
|
||||
|
||||
// wildcard w/port 0
|
||||
wildcardZeroPkt = new DatagramPacket(buf, 0, buf.length);
|
||||
wildcardZeroPkt.setAddress(wildcardAddr);
|
||||
wildcardZeroPkt.setPort(0);
|
||||
|
||||
// wildcard addr w/valid port
|
||||
// Not currently tested. See JDK-8236807
|
||||
wildcardValidPkt = new DatagramPacket(buf, 0, buf.length);
|
||||
wildcardValidPkt.setAddress(wildcardAddr);
|
||||
wildcardValidPkt.setPort(datagramSocket.getLocalPort());
|
||||
}
|
||||
|
||||
@DataProvider(name = "data")
|
||||
public Object[][] variants() {
|
||||
return new Object[][]{
|
||||
{ datagramSocket, loopbackZeroPkt },
|
||||
{ datagramSocket, wildcardZeroPkt },
|
||||
// Re-enable when JDK-8236807 fixed
|
||||
//{ datagramSocket, wildcardValidPkt },
|
||||
|
||||
{ datagramSocketAdaptor, loopbackZeroPkt },
|
||||
{ datagramSocketAdaptor, wildcardZeroPkt },
|
||||
// Re-enable when JDK-8236807 fixed
|
||||
//{ datagramSocketAdaptor, wildcardValidPkt },
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "data")
|
||||
public void testSend(DatagramSocket ds, DatagramPacket pkt) {
|
||||
assertThrows(SE, () -> ds.send(pkt));
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void tearDown() {
|
||||
datagramSocket.close();
|
||||
datagramSocketAdaptor.close();
|
||||
}
|
||||
}
|
||||
137
test/jdk/java/net/DatagramSocket/SendReceiveMaxSize.java
Normal file
137
test/jdk/java/net/DatagramSocket/SendReceiveMaxSize.java
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2026, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8242885 8250886 8240901
|
||||
* @key randomness
|
||||
* @summary This test verifies that on macOS, the send buffer size is configured
|
||||
* by default so that none of our implementations of the UDP protocol
|
||||
* will fail with a "packet too large" exception when trying to send a
|
||||
* packet of the maximum possible size allowed by the protocol.
|
||||
* However, an exception is expected if the packet size exceeds that
|
||||
* limit.
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.net.IPSupport
|
||||
* @run testng/othervm SendReceiveMaxSize
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true SendReceiveMaxSize
|
||||
* @run testng/othervm -Djava.net.preferIPv6Addresses=true SendReceiveMaxSize
|
||||
*/
|
||||
|
||||
import jdk.test.lib.RandomFactory;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.util.Random;
|
||||
|
||||
import static java.net.StandardSocketOptions.SO_RCVBUF;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
public class SendReceiveMaxSize {
|
||||
private int BUF_LIMIT;
|
||||
private InetAddress HOST_ADDR;
|
||||
private final static int IPV4_SNDBUF = 65507;
|
||||
private final static int IPV6_SNDBUF = 65527;
|
||||
private final static Class<IOException> IOE = IOException.class;
|
||||
private final static Random random = RandomFactory.getRandom();
|
||||
|
||||
public interface DatagramSocketSupplier {
|
||||
DatagramSocket open() throws IOException;
|
||||
}
|
||||
static DatagramSocketSupplier supplier(DatagramSocketSupplier supplier) { return supplier; }
|
||||
|
||||
@BeforeTest
|
||||
public void setUp() throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
HOST_ADDR = InetAddress.getLocalHost();
|
||||
BUF_LIMIT = (HOST_ADDR instanceof Inet6Address) ? IPV6_SNDBUF : IPV4_SNDBUF;
|
||||
System.out.printf("Host address: %s, Buffer limit: %d%n", HOST_ADDR, BUF_LIMIT);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] invariants() {
|
||||
var ds = supplier(() -> new DatagramSocket());
|
||||
var ms = supplier(() -> new MulticastSocket());
|
||||
var dsa = supplier(() -> DatagramChannel.open().socket());
|
||||
return new Object[][]{
|
||||
{ "DatagramSocket", BUF_LIMIT - 1, ds, null },
|
||||
{ "DatagramSocket", BUF_LIMIT, ds, null },
|
||||
{ "DatagramSocket", BUF_LIMIT + 1, ds, IOE },
|
||||
{ "MulticastSocket", BUF_LIMIT - 1, ms, null },
|
||||
{ "MulticastSocket", BUF_LIMIT, ms, null },
|
||||
{ "MulticastSocket", BUF_LIMIT + 1, ms, IOE },
|
||||
{ "DatagramSocketAdaptor", BUF_LIMIT - 1, dsa, null },
|
||||
{ "DatagramSocketAdaptor", BUF_LIMIT, dsa, null },
|
||||
{ "DatagramSocketAdaptor", BUF_LIMIT + 1, dsa, IOE },
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invariants")
|
||||
public void testSendReceiveMaxSize(String name, int capacity,
|
||||
DatagramSocketSupplier supplier,
|
||||
Class<? extends Exception> exception) throws IOException {
|
||||
try (var receiver = new DatagramSocket(new InetSocketAddress(HOST_ADDR, 0))) {
|
||||
assertTrue(receiver.getOption(SO_RCVBUF) >= capacity,
|
||||
receiver.getOption(SO_RCVBUF) +
|
||||
" for UDP receive buffer too small to hold capacity " +
|
||||
capacity);
|
||||
var port = receiver.getLocalPort();
|
||||
var addr = new InetSocketAddress(HOST_ADDR, port);
|
||||
try (var sender = supplier.open()) {
|
||||
if (!Platform.isOSX()) {
|
||||
if (sender.getSendBufferSize() < capacity)
|
||||
sender.setSendBufferSize(capacity);
|
||||
}
|
||||
byte[] testData = new byte[capacity];
|
||||
random.nextBytes(testData);
|
||||
var sendPkt = new DatagramPacket(testData, capacity, addr);
|
||||
|
||||
if (exception != null) {
|
||||
Exception ex = expectThrows(IOE, () -> sender.send(sendPkt));
|
||||
System.out.println(name + " got expected exception: " + ex);
|
||||
} else {
|
||||
sender.send(sendPkt);
|
||||
var receivePkt = new DatagramPacket(new byte[capacity], capacity);
|
||||
receiver.receive(receivePkt);
|
||||
|
||||
// check packet data has been fragmented and re-assembled correctly at receiver
|
||||
assertEquals(receivePkt.getLength(), capacity);
|
||||
assertEquals(receivePkt.getData(), testData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
126
test/jdk/java/net/DatagramSocket/SendSize.java
Normal file
126
test/jdk/java/net/DatagramSocket/SendSize.java
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
*
|
||||
* @bug 4095393
|
||||
* @test main SendSize
|
||||
* @summary this tests a regression in 1.2, beta 2 and earlier where
|
||||
* the DatagramPackets sent the entire buffer, not the buffer length
|
||||
* of the packet.
|
||||
*
|
||||
* @author Benjamin Renaud
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class SendSize {
|
||||
static final int bufferLength = 512;
|
||||
static final int packetLength = 256;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
DatagramSocket serverSocket = new DatagramSocket(
|
||||
new InetSocketAddress(InetAddress.getLocalHost(), 0)
|
||||
);
|
||||
Thread server = new ServerThread(serverSocket);
|
||||
server.start();
|
||||
Thread client = new ClientThread(serverSocket.getLocalPort());
|
||||
client.start();
|
||||
server.join();
|
||||
client.join();
|
||||
}
|
||||
|
||||
static class ServerThread extends Thread {
|
||||
DatagramSocket server;
|
||||
|
||||
ServerThread(DatagramSocket server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
System.err.println("started server thread: " + server);
|
||||
byte[] buf = new byte[1024];
|
||||
for (int i = 0; i < 10; i++) {
|
||||
DatagramPacket receivePacket = new DatagramPacket(buf,
|
||||
buf.length);
|
||||
server.receive(receivePacket);
|
||||
int len = receivePacket.getLength();
|
||||
switch (len) {
|
||||
case packetLength:
|
||||
System.out.println("receive length is: " + len);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException(
|
||||
"receive length is: " + len +
|
||||
", send length: " + packetLength +
|
||||
", buffer length: " + buf.length);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("caught: " + e);
|
||||
} finally {
|
||||
if (server != null) { server.close(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ClientThread extends Thread {
|
||||
|
||||
int serverPort;
|
||||
DatagramSocket client;
|
||||
InetAddress host;
|
||||
|
||||
ClientThread(int serverPort)throws IOException {
|
||||
this.serverPort = serverPort;
|
||||
this.host = InetAddress.getLocalHost();
|
||||
this.client = new DatagramSocket();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
System.err.println("started client thread: " + client);
|
||||
byte[] buf = new byte[bufferLength];
|
||||
DatagramPacket sendPacket =
|
||||
new DatagramPacket(buf, packetLength,
|
||||
host, serverPort);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
client.send(sendPacket);
|
||||
}
|
||||
System.err.println("sent 10 packets");
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("caught: " + e);
|
||||
} finally {
|
||||
if (client != null) { client.close(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4132931
|
||||
* @summary DatagramSocket should use a factory for its impl
|
||||
*
|
||||
* @compile/module=java.base java/net/MyDatagramSocketImplFactory.java
|
||||
* @run main/othervm ADatagramSocket
|
||||
*/
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class ADatagramSocket {
|
||||
public static void main(String[] args) throws Exception {
|
||||
// testing out setDatagramSocketImplFactory
|
||||
System.err.println("setting DatagramSocketImplFactory...");
|
||||
try {
|
||||
DatagramSocket.setDatagramSocketImplFactory(new java.net.MyDatagramSocketImplFactory());
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Setting DatagramSocketImplFactory failed!");
|
||||
}
|
||||
|
||||
QuoteServerThread server = new QuoteServerThread();
|
||||
int port = server.getPort();
|
||||
System.out.println("Server port is " + port);
|
||||
server.start();
|
||||
// Wait server thread to reach receive call
|
||||
server.readyToStart.await();
|
||||
|
||||
// get a datagram socket
|
||||
DatagramSocket socket = new DatagramSocket();
|
||||
|
||||
// send request
|
||||
byte[] buf = new byte[256];
|
||||
InetAddress address = InetAddress.getLocalHost();
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, port);
|
||||
socket.send(packet);
|
||||
|
||||
// get response
|
||||
packet = new DatagramPacket(buf, buf.length);
|
||||
socket.receive(packet);
|
||||
|
||||
// display response
|
||||
String received = new String(packet.getData(), 0);
|
||||
System.err.println("Success!! Server current time is: " + received);
|
||||
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
|
||||
class QuoteServerThread extends Thread {
|
||||
|
||||
protected DatagramSocket socket = null;
|
||||
private final int port;
|
||||
final CountDownLatch readyToStart = new CountDownLatch(1);
|
||||
|
||||
public QuoteServerThread() throws IOException {
|
||||
this("QuoteServerThread");
|
||||
}
|
||||
|
||||
public QuoteServerThread(String name) throws IOException {
|
||||
super(name);
|
||||
socket = new DatagramSocket(0, InetAddress.getLocalHost());
|
||||
port = socket.getLocalPort();
|
||||
}
|
||||
public int getPort(){
|
||||
return port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
byte[] buf = new byte[256];
|
||||
|
||||
// receive request
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
||||
// Notify client that server is ready to receive packet
|
||||
readyToStart.countDown();
|
||||
socket.receive(packet);
|
||||
|
||||
// figure out response
|
||||
String dString = null;
|
||||
dString = new Date().toString();
|
||||
buf = dString.getBytes();
|
||||
|
||||
// send the response to the client at "address" and "port"
|
||||
InetAddress address = packet.getAddress();
|
||||
int port = packet.getPort();
|
||||
packet = new DatagramPacket(buf, buf.length, address, port);
|
||||
socket.send(packet);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
public class MyDatagramSocketImplFactory implements DatagramSocketImplFactory {
|
||||
static class MyDatagramSocketImpl extends DatagramSocketImpl {
|
||||
DatagramSocket ds;
|
||||
|
||||
@Override
|
||||
protected void create() throws SocketException {
|
||||
try {
|
||||
ds = DatagramChannel.open().socket();
|
||||
} catch (IOException ex) { throw new SocketException(ex.getMessage());}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bind(int lport, InetAddress laddr) throws SocketException {
|
||||
ds.bind(new InetSocketAddress(laddr, lport));
|
||||
localPort = ds.getLocalPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void send(DatagramPacket p) throws IOException {
|
||||
ds.send(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int peek(InetAddress i) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int peekData(DatagramPacket p) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void receive(DatagramPacket p) throws IOException {
|
||||
ds.receive(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setTimeToLive(int ttl) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTimeToLive() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void join(InetAddress inetaddr) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void leave(InetAddress inetaddr) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close() {
|
||||
ds.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOption(int optID, Object value) throws SocketException {
|
||||
try {
|
||||
if (optID == SocketOptions.SO_SNDBUF) {
|
||||
if (((Integer) value).intValue() < 0)
|
||||
throw new IllegalArgumentException("Invalid send buffer size:" + value);
|
||||
ds.setOption(StandardSocketOptions.SO_SNDBUF, (Integer) value);
|
||||
} else if (optID == SocketOptions.SO_RCVBUF) {
|
||||
if (((Integer) value).intValue() < 0)
|
||||
throw new IllegalArgumentException("Invalid recv buffer size:" + value);
|
||||
ds.setOption(StandardSocketOptions.SO_RCVBUF, (Integer) value);
|
||||
} else if (optID == SocketOptions.SO_REUSEADDR) {
|
||||
ds.setOption(StandardSocketOptions.SO_REUSEADDR, (Boolean) value);
|
||||
} else if (optID == SocketOptions.SO_REUSEPORT) {
|
||||
ds.setOption(StandardSocketOptions.SO_REUSEPORT, (Boolean) value);
|
||||
} else if (optID == SocketOptions.SO_BROADCAST) {
|
||||
ds.setOption(StandardSocketOptions.SO_BROADCAST, (Boolean) value);
|
||||
} else if (optID == SocketOptions.IP_TOS) {
|
||||
int i = ((Integer) value).intValue();
|
||||
if (i < 0 || i > 255)
|
||||
throw new IllegalArgumentException("Invalid IP_TOS value: " + value);
|
||||
ds.setOption(StandardSocketOptions.IP_TOS, (Integer) value);
|
||||
} else if (optID == SocketOptions.IP_MULTICAST_LOOP) {
|
||||
boolean enable = (boolean) value;
|
||||
// Legacy ds.setOption expects true to mean 'disabled'
|
||||
ds.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, !enable);
|
||||
} else {
|
||||
throw new AssertionError("unknown option :" + optID);
|
||||
}
|
||||
} catch (IOException ex) { throw new SocketException(ex.getMessage()); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOption(int optID) throws SocketException {
|
||||
try {
|
||||
if (optID == SocketOptions.SO_SNDBUF) {
|
||||
return ds.getOption(StandardSocketOptions.SO_SNDBUF);
|
||||
} else if (optID == SocketOptions.SO_RCVBUF) {
|
||||
return ds.getOption(StandardSocketOptions.SO_RCVBUF);
|
||||
} else if (optID == SocketOptions.SO_REUSEADDR) {
|
||||
return ds.getOption(StandardSocketOptions.SO_REUSEADDR);
|
||||
} else if (optID == SocketOptions.SO_REUSEPORT) {
|
||||
return ds.getOption(StandardSocketOptions.SO_REUSEPORT);
|
||||
} else if (optID == SocketOptions.SO_BROADCAST) {
|
||||
return ds.getOption(StandardSocketOptions.SO_BROADCAST);
|
||||
} else if (optID == SocketOptions.IP_TOS) {
|
||||
return ds.getOption(StandardSocketOptions.IP_TOS);
|
||||
} else if (optID == SocketOptions.IP_MULTICAST_LOOP) {
|
||||
boolean disabled = (boolean) ds.getOption(StandardSocketOptions.IP_MULTICAST_LOOP);
|
||||
// Legacy getOption returns true when disabled
|
||||
return Boolean.valueOf(!disabled);
|
||||
} else {
|
||||
throw new AssertionError("unknown option: " + optID);
|
||||
}
|
||||
} catch (IOException ex) { throw new SocketException(ex.getMessage()); }
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public MyDatagramSocketImpl createDatagramSocketImpl() {
|
||||
return new MyDatagramSocketImpl();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4173717 8243488
|
||||
* @summary Check that setReceiveBufferSize and getReceiveBufferSize work as expected
|
||||
* @run testng SetGetReceiveBufferSize
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true SetGetReceiveBufferSize
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
public class SetGetReceiveBufferSize {
|
||||
static final Class<SocketException> SE = SocketException.class;
|
||||
static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface DatagramSocketSupplier {
|
||||
DatagramSocket open() throws IOException;
|
||||
}
|
||||
static DatagramSocketSupplier supplier(DatagramSocketSupplier supplier) { return supplier; }
|
||||
|
||||
@DataProvider
|
||||
public Object[][] invariants() {
|
||||
return new Object[][]{
|
||||
{"DatagramSocket", supplier(() -> new DatagramSocket())},
|
||||
{"MulticastSocket", supplier(() -> new MulticastSocket())},
|
||||
{"DatagramSocketAdaptor", supplier(() -> DatagramChannel.open().socket())},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invariants")
|
||||
public void testSetInvalidBufferSize(String name, DatagramSocketSupplier supplier) throws IOException {
|
||||
var invalidArgs = new int[]{ -1, 0 };
|
||||
|
||||
try (var socket = supplier.open()) {
|
||||
for (int i : invalidArgs) {
|
||||
Exception ex = expectThrows(IAE, () -> socket.setReceiveBufferSize(i));
|
||||
System.out.println(name + " got expected exception: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invariants")
|
||||
public void testSetAndGetBufferSize(String name, DatagramSocketSupplier supplier) throws IOException {
|
||||
var validArgs = new int[]{ 1234, 2345, 3456 };
|
||||
|
||||
try (var socket = supplier.open()) {
|
||||
for (int i : validArgs) {
|
||||
socket.setReceiveBufferSize(i);
|
||||
assertEquals(socket.getReceiveBufferSize(), i, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invariants")
|
||||
public void testSetGetAfterClose(String name, DatagramSocketSupplier supplier) throws IOException {
|
||||
var socket = supplier.open();
|
||||
socket.close();
|
||||
|
||||
Exception setException = expectThrows(SE, () -> socket.setReceiveBufferSize(2345));
|
||||
System.out.println(name + " got expected exception: " + setException);
|
||||
|
||||
Exception getException = expectThrows(SE, () -> socket.getReceiveBufferSize());
|
||||
System.out.println(name + " got expected exception: " + getException);
|
||||
}
|
||||
}
|
||||
114
test/jdk/java/net/DatagramSocket/SetGetSendBufferSize.java
Normal file
114
test/jdk/java/net/DatagramSocket/SetGetSendBufferSize.java
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8243488
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Platform
|
||||
* @summary Check that setSendBufferSize and getSendBufferSize work as expected
|
||||
* @run testng SetGetSendBufferSize
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true SetGetSendBufferSize
|
||||
*/
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
public class SetGetSendBufferSize {
|
||||
static final Class<SocketException> SE = SocketException.class;
|
||||
static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
|
||||
|
||||
public interface DatagramSocketSupplier {
|
||||
DatagramSocket open() throws IOException;
|
||||
}
|
||||
static DatagramSocketSupplier supplier(DatagramSocketSupplier supplier) { return supplier; }
|
||||
|
||||
@DataProvider
|
||||
public Object[][] invariants() {
|
||||
return new Object[][]{
|
||||
{"DatagramSocket", supplier(() -> new DatagramSocket())},
|
||||
{"MulticastSocket", supplier(() -> new MulticastSocket())},
|
||||
{"DatagramSocketAdaptor", supplier(() -> DatagramChannel.open().socket())},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invariants")
|
||||
public void testSetInvalidBufferSize(String name, DatagramSocketSupplier supplier) throws IOException {
|
||||
var invalidArgs = new int[]{ -1, 0 };
|
||||
|
||||
try (var socket = supplier.open()) {
|
||||
for (int i : invalidArgs) {
|
||||
Exception ex = expectThrows(IAE, () -> socket.setSendBufferSize(i));
|
||||
System.out.println(name + " got expected exception: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invariants")
|
||||
public void testSetAndGetBufferSize(String name, DatagramSocketSupplier supplier) throws IOException {
|
||||
var validArgs = new int[]{ 2345, 3456 };
|
||||
|
||||
try (var socket = supplier.open()) {
|
||||
for (int i : validArgs) {
|
||||
socket.setSendBufferSize(i);
|
||||
assertEquals(socket.getSendBufferSize(), i, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invariants")
|
||||
public void testInitialSendBufferSize(String name, DatagramSocketSupplier supplier) throws IOException {
|
||||
if (Platform.isOSX()) {
|
||||
try (var socket = supplier.open()){
|
||||
assertTrue(socket.getSendBufferSize() >= 65507, name);
|
||||
if (IPSupport.hasIPv6() && !IPSupport.preferIPv4Stack()) {
|
||||
assertEquals(socket.getSendBufferSize(), 65527, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invariants")
|
||||
public void testSetGetAfterClose(String name, DatagramSocketSupplier supplier) throws IOException {
|
||||
var socket = supplier.open();
|
||||
socket.close();
|
||||
|
||||
Exception setException = expectThrows(SE, () -> socket.setSendBufferSize(2345));
|
||||
System.out.println(name + " got expected exception: " + setException);
|
||||
|
||||
Exception getException = expectThrows(SE, () -> socket.getSendBufferSize());
|
||||
System.out.println(name + " got expected exception: " + getException);
|
||||
}
|
||||
}
|
||||
58
test/jdk/java/net/DatagramSocket/SupportedOptionsCheck.java
Normal file
58
test/jdk/java/net/DatagramSocket/SupportedOptionsCheck.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8234148
|
||||
* @library /test/lib
|
||||
* @summary checks that the DatagramSocket supportedOptions set contains all
|
||||
* MulticastSocket socket options
|
||||
* @run testng SupportedOptionsCheck
|
||||
*/
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
public class SupportedOptionsCheck {
|
||||
|
||||
@Test
|
||||
public void checkMulticastOptionsAreReturned() throws Exception {
|
||||
try (DatagramSocket ds = new DatagramSocket())
|
||||
{
|
||||
Set<?> options = ds.supportedOptions();
|
||||
Set<?> multicastOptions = Set.of(
|
||||
StandardSocketOptions.IP_MULTICAST_IF,
|
||||
StandardSocketOptions.IP_MULTICAST_TTL,
|
||||
StandardSocketOptions.IP_MULTICAST_LOOP);
|
||||
|
||||
if (!Platform.isWindows())
|
||||
assertTrue(options.containsAll(multicastOptions));
|
||||
}
|
||||
}
|
||||
}
|
||||
109
test/jdk/java/net/DatagramSocket/TestAfterClose.java
Normal file
109
test/jdk/java/net/DatagramSocket/TestAfterClose.java
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6505016
|
||||
* @summary Socket spec should clarify what getInetAddress/getPort/etc return after the Socket is closed
|
||||
* @run main TestAfterClose
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
|
||||
public class TestAfterClose
|
||||
{
|
||||
static int failCount;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
DatagramSocket socket = new DatagramSocket();
|
||||
socket.connect(InetAddress.getLoopbackAddress(), 5001);
|
||||
test(socket, true);
|
||||
|
||||
socket = new DatagramSocket();
|
||||
test(socket, false);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
|
||||
if (failCount > 0)
|
||||
throw new RuntimeException("Failed: failcount = " + failCount);
|
||||
|
||||
}
|
||||
|
||||
static void test(DatagramSocket socket, boolean connected) throws IOException {
|
||||
//Before Close
|
||||
int socketPort = socket.getPort();
|
||||
InetAddress socketInetAddress = socket.getInetAddress();
|
||||
SocketAddress socketRemoteSocketAddress = socket.getRemoteSocketAddress();
|
||||
|
||||
//After Close
|
||||
socket.close();
|
||||
|
||||
if (connected ? !(socket.getPort() == socketPort)
|
||||
: !(socket.getPort() == -1)) {
|
||||
System.out.println("Socket.getPort failed");
|
||||
failCount++;
|
||||
}
|
||||
|
||||
if (connected ? !socket.getInetAddress().equals(socketInetAddress)
|
||||
: !(socket.getInetAddress() == null)) {
|
||||
System.out.println("Socket.getInetAddress failed");
|
||||
failCount++;
|
||||
}
|
||||
|
||||
if (connected ? !socket.getRemoteSocketAddress().equals(socketRemoteSocketAddress)
|
||||
: !(socket.getRemoteSocketAddress() == null)) {
|
||||
System.out.println("Socket.getRemoteSocketAddresss failed");
|
||||
failCount++;
|
||||
}
|
||||
|
||||
if (socket.getLocalPort() != -1) {
|
||||
System.out.println("Socket.getLocalPort failed");
|
||||
failCount++;
|
||||
}
|
||||
|
||||
if (socket.getLocalAddress() != null) {
|
||||
System.out.println("Socket.getLocalAddress failed");
|
||||
failCount++;
|
||||
}
|
||||
|
||||
if (socket.getLocalSocketAddress() != null) {
|
||||
System.out.println("Socket.getLocalSocketAddress failed");
|
||||
failCount++;
|
||||
}
|
||||
|
||||
if (connected && !socket.isConnected()) {
|
||||
System.out.println("Socket.isConnected failed");
|
||||
failCount++;
|
||||
}
|
||||
|
||||
if (!socket.isBound()) {
|
||||
System.out.println("Socket.isBound failed");
|
||||
failCount++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 2026, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib
|
||||
* @modules java.management java.base/java.io:+open java.base/java.net:+open
|
||||
* java.base/sun.nio.ch:+open
|
||||
* @run main/othervm/timeout=480 UnreferencedDatagramSockets
|
||||
* @run main/othervm/timeout=480 -Djava.net.preferIPv4Stack=true UnreferencedDatagramSockets
|
||||
* @summary Check that unreferenced datagram sockets are closed
|
||||
*/
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import com.sun.management.UnixOperatingSystemMXBean;
|
||||
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
public class UnreferencedDatagramSockets {
|
||||
|
||||
/**
|
||||
* The set of sockets we have to check up on.
|
||||
*/
|
||||
final static ArrayDeque<NamedWeak> pendingSockets = new ArrayDeque<>(5);
|
||||
|
||||
/**
|
||||
* Queued objects when they are unreferenced.
|
||||
*/
|
||||
final static ReferenceQueue<Object> pendingQueue = new ReferenceQueue<>();
|
||||
|
||||
// Server to echo a datagram packet
|
||||
static class Server implements Runnable {
|
||||
|
||||
DatagramSocket ss;
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
Server() throws IOException {
|
||||
ss = new DatagramSocket(0, getHost());
|
||||
System.out.printf(" DatagramServer addr: %s: %d%n",
|
||||
this.getHost(), this.getPort());
|
||||
pendingSockets.add(new NamedWeak(ss, pendingQueue, "serverDatagramSocket"));
|
||||
extractRefs(ss, "serverDatagramSocket");
|
||||
}
|
||||
|
||||
InetAddress getHost() throws UnknownHostException {
|
||||
InetAddress localhost = lookupLocalHost();
|
||||
return localhost;
|
||||
}
|
||||
|
||||
int getPort() {
|
||||
return ss.getLocalPort();
|
||||
}
|
||||
|
||||
// Receive a byte and send back a byte
|
||||
public void run() {
|
||||
try {
|
||||
byte[] buffer = new byte[50];
|
||||
DatagramPacket p = new DatagramPacket(buffer, buffer.length);
|
||||
ss.receive(p);
|
||||
buffer[0] += 1;
|
||||
ss.send(p); // send back +1
|
||||
latch.await(); // wait for the client to receive the packet
|
||||
// do NOT close but 'forget' the datagram socket reference
|
||||
ss = null;
|
||||
} catch (Exception ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static InetAddress lookupLocalHost() throws UnknownHostException {
|
||||
return InetAddress.getByName("localhost"); //.getLocalHost();
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
|
||||
// Create and close a DatagramSocket to warm up the FD count for side effects.
|
||||
try (DatagramSocket s = new DatagramSocket(0, lookupLocalHost())) {
|
||||
// no-op; close immediately
|
||||
s.getLocalPort(); // no-op
|
||||
}
|
||||
|
||||
long fdCount0 = getFdCount();
|
||||
listProcFD();
|
||||
|
||||
// start a server
|
||||
Server svr = new Server();
|
||||
Thread thr = new Thread(svr);
|
||||
thr.start();
|
||||
|
||||
DatagramSocket client = new DatagramSocket(0, lookupLocalHost());
|
||||
client.connect(svr.getHost(), svr.getPort());
|
||||
pendingSockets.add(new NamedWeak(client, pendingQueue, "clientDatagramSocket"));
|
||||
extractRefs(client, "clientDatagramSocket");
|
||||
|
||||
byte[] msg = new byte[1];
|
||||
msg[0] = 1;
|
||||
DatagramPacket p = new DatagramPacket(msg, msg.length, svr.getHost(), svr.getPort());
|
||||
client.send(p);
|
||||
|
||||
p = new DatagramPacket(msg, msg.length);
|
||||
client.receive(p);
|
||||
svr.latch.countDown(); // unblock the server
|
||||
|
||||
|
||||
System.out.printf("echo received from: %s%n", p.getSocketAddress());
|
||||
if (msg[0] != 2) {
|
||||
throw new AssertionError("incorrect data received: expected: 2, actual: " + msg[0]);
|
||||
}
|
||||
|
||||
// Do NOT close the DatagramSocket; forget it
|
||||
|
||||
Object ref;
|
||||
int loops = 20;
|
||||
while (!pendingSockets.isEmpty() && loops-- > 0) {
|
||||
ref = pendingQueue.remove(1000L);
|
||||
if (ref != null) {
|
||||
pendingSockets.remove(ref);
|
||||
System.out.printf(" ref freed: %s, remaining: %d%n", ref, pendingSockets.size());
|
||||
} else {
|
||||
client = null;
|
||||
p = null;
|
||||
msg = null;
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
|
||||
thr.join();
|
||||
|
||||
// List the open file descriptors
|
||||
long fdCount = getFdCount();
|
||||
System.out.printf("Initial fdCount: %d, final fdCount: %d%n", fdCount0, fdCount);
|
||||
listProcFD();
|
||||
|
||||
if (loops == 0) {
|
||||
throw new AssertionError("Not all references reclaimed");
|
||||
}
|
||||
}
|
||||
|
||||
// Get the count of open file descriptors, or -1 if not available
|
||||
private static long getFdCount() {
|
||||
OperatingSystemMXBean mxBean = ManagementFactory.getOperatingSystemMXBean();
|
||||
return (mxBean instanceof UnixOperatingSystemMXBean)
|
||||
? ((UnixOperatingSystemMXBean) mxBean).getOpenFileDescriptorCount()
|
||||
: -1L;
|
||||
}
|
||||
|
||||
// Reflect to find references in the datagram implementation that will be gc'd
|
||||
private static void extractRefs(DatagramSocket s, String name) {
|
||||
try {
|
||||
Field datagramSocketField = DatagramSocket.class.getDeclaredField("delegate");
|
||||
datagramSocketField.setAccessible(true);
|
||||
|
||||
// DatagramSocket using DatagramSocketAdaptor
|
||||
Object DatagramSocket = datagramSocketField.get(s);
|
||||
assert DatagramSocket.getClass() == Class.forName("sun.nio.ch.DatagramSocketAdaptor");
|
||||
|
||||
Method m = DatagramSocket.class.getDeclaredMethod("getChannel");
|
||||
m.setAccessible(true);
|
||||
DatagramChannel datagramChannel = (DatagramChannel) m.invoke(DatagramSocket);
|
||||
|
||||
assert datagramChannel.getClass() == Class.forName("sun.nio.ch.DatagramChannelImpl");
|
||||
|
||||
Field fileDescriptorField = datagramChannel.getClass().getDeclaredField("fd");
|
||||
fileDescriptorField.setAccessible(true);
|
||||
FileDescriptor fileDescriptor = (FileDescriptor) fileDescriptorField.get(datagramChannel);
|
||||
extractRefs(fileDescriptor, name);
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw new AssertionError("missing field", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void extractRefs(FileDescriptor fileDescriptor, String name) {
|
||||
Object cleanup = null;
|
||||
int rawfd = -1;
|
||||
try {
|
||||
if (fileDescriptor != null) {
|
||||
Field fd1Field = FileDescriptor.class.getDeclaredField("fd");
|
||||
fd1Field.setAccessible(true);
|
||||
rawfd = fd1Field.getInt(fileDescriptor);
|
||||
|
||||
Field cleanupfdField = FileDescriptor.class.getDeclaredField("cleanup");
|
||||
cleanupfdField.setAccessible(true);
|
||||
cleanup = cleanupfdField.get(fileDescriptor);
|
||||
pendingSockets.add(new NamedWeak(fileDescriptor, pendingQueue,
|
||||
name + "::fileDescriptor: " + rawfd));
|
||||
pendingSockets.add(new NamedWeak(cleanup, pendingQueue, name + "::fdCleanup: " + rawfd));
|
||||
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
||||
ex.printStackTrace();
|
||||
throw new AssertionError("missing field", ex);
|
||||
} finally {
|
||||
System.out.print(String.format(" %s:: fd: %s, fd: %d, cleanup: %s%n",
|
||||
name, fileDescriptor, rawfd, cleanup));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to list the open file descriptors (if supported by the 'lsof' command).
|
||||
*/
|
||||
static void listProcFD() {
|
||||
List<String> lsofDirs = List.of("/usr/bin", "/usr/sbin");
|
||||
Optional<Path> lsof = lsofDirs.stream()
|
||||
.map(s -> Paths.get(s, "lsof"))
|
||||
.filter(f -> Files.isExecutable(f))
|
||||
.findFirst();
|
||||
lsof.ifPresent(exe -> {
|
||||
try {
|
||||
System.out.printf("Open File Descriptors:%n");
|
||||
long pid = ProcessHandle.current().pid();
|
||||
ProcessBuilder pb = new ProcessBuilder(exe.toString(), "-p", Integer.toString((int) pid));
|
||||
pb.inheritIO();
|
||||
Process p = pb.start();
|
||||
p.waitFor(10, TimeUnit.SECONDS);
|
||||
} catch (IOException | InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Simple class to identify which refs have been queued
|
||||
static class NamedWeak extends WeakReference<Object> {
|
||||
private final String name;
|
||||
|
||||
NamedWeak(Object o, ReferenceQueue<Object> queue, String name) {
|
||||
super(o, queue);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + "; " + super.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
136
test/jdk/java/net/DatagramSocketImpl/CheckDiscard.java
Normal file
136
test/jdk/java/net/DatagramSocketImpl/CheckDiscard.java
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4433616
|
||||
* @summary Test that packet discarding is done at impl level
|
||||
*/
|
||||
import java.net.*;
|
||||
|
||||
public class CheckDiscard {
|
||||
|
||||
CheckDiscard() throws Exception {
|
||||
|
||||
DatagramSocket s = new DatagramSocket();
|
||||
|
||||
/*
|
||||
* Create two sender threads
|
||||
*/
|
||||
Sender s1 = new Sender( s.getLocalPort() );
|
||||
Sender s2 = new Sender( s.getLocalPort() );
|
||||
|
||||
/*
|
||||
* "connect" to sender 1
|
||||
*/
|
||||
InetAddress ia = InetAddress.getLocalHost();
|
||||
s.connect( ia, s1.getLocalPort() );
|
||||
|
||||
/*
|
||||
* Kick off the senders
|
||||
*/
|
||||
(new Thread(s1)).start();
|
||||
(new Thread(s2)).start();
|
||||
|
||||
/*
|
||||
* Receive packets and verify that they came from the
|
||||
* right sender
|
||||
*/
|
||||
byte b[] = new byte[512];
|
||||
DatagramPacket p = new DatagramPacket(b, b.length);
|
||||
s.setSoTimeout(4000);
|
||||
try {
|
||||
for (int i=0; i<20; i++) {
|
||||
s.receive(p);
|
||||
if ((p.getPort() != s1.getLocalPort()) ||
|
||||
(!p.getAddress().equals(ia))) {
|
||||
throw new Exception("Received packet from wrong sender");
|
||||
}
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally check if either sender threw an exception
|
||||
*/
|
||||
Exception e;
|
||||
e = s1.getException();
|
||||
if (e != null) throw e;
|
||||
e = s2.getException();
|
||||
if (e != null) throw e;
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
new CheckDiscard();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class Sender implements Runnable {
|
||||
|
||||
Exception exc = null;
|
||||
DatagramSocket s;
|
||||
int port;
|
||||
|
||||
Sender(int port) throws Exception {
|
||||
s = new DatagramSocket();
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public int getLocalPort() {
|
||||
return s.getLocalPort();
|
||||
}
|
||||
|
||||
public void setException(Exception e) {
|
||||
exc = e;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return exc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send 10 packets to the receiver
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
byte b[] = "Hello".getBytes();
|
||||
DatagramPacket p = new DatagramPacket(b, b.length);
|
||||
p.setAddress( InetAddress.getLocalHost() );
|
||||
p.setPort( port );
|
||||
|
||||
for (int i=0; i<10; i++) {
|
||||
s.send(p);
|
||||
Thread.currentThread().sleep(1000);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
setException(e);
|
||||
}
|
||||
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
118
test/jdk/java/net/DatagramSocketImpl/TestCreate.java
Normal file
118
test/jdk/java/net/DatagramSocketImpl/TestCreate.java
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8238231
|
||||
* @summary test that DatagramSocket calls java.net.DatagramSocketImpl::create
|
||||
* @run testng/othervm TestCreate
|
||||
*/
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.DatagramSocketImpl;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
public class TestCreate {
|
||||
|
||||
@Test
|
||||
public void datagramSocketImpl() throws IOException {
|
||||
CustomDatagramSocketImpl dsi = new CustomDatagramSocketImpl();
|
||||
CustomDatagramSocket ds = new CustomDatagramSocket(dsi);
|
||||
ds.bind(new InetSocketAddress(0));
|
||||
assertTrue(dsi.created.get(), "new CustomDatagramSocket(dsi)");
|
||||
|
||||
CustomDatagramSocketImpl dsi2 = new CustomDatagramSocketImpl();
|
||||
CustomDatagramSocketImpl dsi3 = new CustomDatagramSocketImpl();
|
||||
Iterator<CustomDatagramSocketImpl> iterator = List.of(dsi2, dsi3).iterator();
|
||||
DatagramSocket.setDatagramSocketImplFactory(() -> iterator.next());
|
||||
|
||||
DatagramSocket ds2 = new DatagramSocket(null);
|
||||
assertTrue(dsi2.created.get(), "new DatagramSocket()");
|
||||
|
||||
MulticastSocket ds3 = new MulticastSocket(null);
|
||||
assertTrue(dsi3.created.get(), "new MulticastSocket()");
|
||||
}
|
||||
|
||||
static class CustomDatagramSocket extends DatagramSocket {
|
||||
CustomDatagramSocket(DatagramSocketImpl impl) {
|
||||
super(impl);
|
||||
}
|
||||
}
|
||||
|
||||
// A DatagramSocketImpl that delegates the three new-style socket option
|
||||
// methods to the default java.net.DatagramSocketImpl implementation.
|
||||
static class CustomDatagramSocketImpl extends DatagramSocketImpl {
|
||||
|
||||
final AtomicBoolean created = new AtomicBoolean(false);
|
||||
|
||||
@Override
|
||||
public <T> void setOption(SocketOption<T> name, T value) throws IOException {
|
||||
super.setOption(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketOption<?>> supportedOptions() {
|
||||
return super.supportedOptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getOption(SocketOption<T> name) throws IOException {
|
||||
return super.getOption(name);
|
||||
}
|
||||
|
||||
// --
|
||||
@Override protected void create() {
|
||||
if (created.compareAndExchange(false, true)) {
|
||||
throw new AssertionError("create called twice");
|
||||
}
|
||||
}
|
||||
@Override protected void bind(int lport, InetAddress laddr) { }
|
||||
@Override protected void send(DatagramPacket p) { }
|
||||
@Override protected int peek(InetAddress i) { return 0; }
|
||||
@Override protected int peekData(DatagramPacket p) { return 0; }
|
||||
@Override protected void receive(DatagramPacket p) { }
|
||||
@Override protected void setTimeToLive(int ttl) { }
|
||||
@Override protected int getTimeToLive() { return 0; }
|
||||
@Override protected void join(InetAddress inetaddr) { }
|
||||
@Override protected void leave(InetAddress inetaddr) { }
|
||||
@Override protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) { }
|
||||
@Override protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) { }
|
||||
@Override protected void close() { }
|
||||
@Override public void setOption(int optID, Object value) { }
|
||||
@Override public Object getOption(int optID) { return null; }
|
||||
}
|
||||
}
|
||||
112
test/jdk/java/net/DatagramSocketImpl/TestDefaultBehavior.java
Normal file
112
test/jdk/java/net/DatagramSocketImpl/TestDefaultBehavior.java
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8224477
|
||||
* @summary Basic test for java.net.DatagramSocketImpl default behavior
|
||||
* @run testng TestDefaultBehavior
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocketImpl;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.util.Set;
|
||||
import org.testng.annotations.Test;
|
||||
import static java.lang.Boolean.*;
|
||||
import static java.net.StandardSocketOptions.*;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
public class TestDefaultBehavior {
|
||||
|
||||
static final Class<NullPointerException> NPE = NullPointerException.class;
|
||||
static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
|
||||
|
||||
@Test
|
||||
public void datagramSocketImpl() {
|
||||
CustomDatagramSocketImpl dsi = new CustomDatagramSocketImpl();
|
||||
|
||||
assertEquals(dsi.supportedOptions().size(), 0);
|
||||
|
||||
expectThrows(NPE, () -> dsi.setOption(null, null));
|
||||
expectThrows(NPE, () -> dsi.setOption(null, 1));
|
||||
expectThrows(UOE, () -> dsi.setOption(SO_RCVBUF, 100));
|
||||
expectThrows(UOE, () -> dsi.setOption(SO_KEEPALIVE, TRUE));
|
||||
expectThrows(UOE, () -> dsi.setOption(SO_KEEPALIVE, FALSE));
|
||||
expectThrows(UOE, () -> dsi.setOption(FAKE_SOCK_OPT, TRUE));
|
||||
expectThrows(UOE, () -> dsi.setOption(FAKE_SOCK_OPT, FALSE));
|
||||
expectThrows(UOE, () -> dsi.setOption(SO_KEEPALIVE, TRUE));
|
||||
|
||||
expectThrows(NPE, () -> dsi.getOption(null));
|
||||
expectThrows(UOE, () -> dsi.getOption(SO_RCVBUF));
|
||||
expectThrows(UOE, () -> dsi.getOption(SO_KEEPALIVE));
|
||||
expectThrows(UOE, () -> dsi.getOption(FAKE_SOCK_OPT));
|
||||
}
|
||||
|
||||
static final SocketOption<Boolean> FAKE_SOCK_OPT = new SocketOption<>() {
|
||||
@Override public String name() { return "FAKE_SOCK_OPT"; }
|
||||
@Override public Class<Boolean> type() { return Boolean.class; }
|
||||
};
|
||||
|
||||
// A DatagramSocketImpl that delegates the three new-style socket option
|
||||
// methods to the default java.net.DatagramSocketImpl implementation.
|
||||
static class CustomDatagramSocketImpl extends DatagramSocketImpl {
|
||||
|
||||
@Override
|
||||
public <T> void setOption(SocketOption<T> name, T value) throws IOException {
|
||||
super.setOption(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketOption<?>> supportedOptions() {
|
||||
return super.supportedOptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getOption(SocketOption<T> name) throws IOException {
|
||||
return super.getOption(name);
|
||||
}
|
||||
|
||||
// --
|
||||
@Override protected void create() { }
|
||||
@Override protected void bind(int lport, InetAddress laddr) { }
|
||||
@Override protected void send(DatagramPacket p) { }
|
||||
@Override protected int peek(InetAddress i) { return 0; }
|
||||
@Override protected int peekData(DatagramPacket p) { return 0; }
|
||||
@Override protected void receive(DatagramPacket p) { }
|
||||
@Override protected void setTimeToLive(int ttl) { }
|
||||
@Override protected int getTimeToLive() { return 0; }
|
||||
@Override protected void join(InetAddress inetaddr) { }
|
||||
@Override protected void leave(InetAddress inetaddr) { }
|
||||
@Override protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) { }
|
||||
@Override protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) { }
|
||||
@Override protected void close() { }
|
||||
@Override public void setOption(int optID, Object value) { }
|
||||
@Override public Object getOption(int optID) { return null; }
|
||||
}
|
||||
}
|
||||
56
test/jdk/java/net/HttpCookie/CookieNegativeMaxAge.java
Normal file
56
test/jdk/java/net/HttpCookie/CookieNegativeMaxAge.java
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8005068
|
||||
* @summary Check that any negative maxAge is treated as "unspecified" and
|
||||
* if header contains cookie with "expires" attribute in the past then cookie
|
||||
* is created with maxAge=0 meaning it is specified to be immediately expired.
|
||||
* @run main CookieNegativeMaxAge
|
||||
*/
|
||||
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.util.List;
|
||||
|
||||
public class CookieNegativeMaxAge {
|
||||
|
||||
public static void main(String... args) {
|
||||
HttpCookie cookie = new HttpCookie("testCookie", "value");
|
||||
cookie.setMaxAge(Integer.MIN_VALUE);
|
||||
if (cookie.hasExpired()) {
|
||||
throw new RuntimeException("Cookie has unexpectedly expired");
|
||||
}
|
||||
|
||||
List<HttpCookie> cookies = HttpCookie.parse("Set-Cookie: " +
|
||||
"expiredCookie=value; expires=Thu, 01 Jan 1970 00:00:00 GMT");
|
||||
if (cookies.size() == 1) {
|
||||
if (cookies.get(0).getMaxAge() != 0) {
|
||||
throw new RuntimeException("Cookie maxAge expected to be 0");
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Header was incorrectly parsed");
|
||||
}
|
||||
}
|
||||
}
|
||||
106
test/jdk/java/net/HttpCookie/ExpiredCookieTest.java
Normal file
106
test/jdk/java/net/HttpCookie/ExpiredCookieTest.java
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8000525
|
||||
* @library /test/lib
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.text.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class ExpiredCookieTest {
|
||||
// lifted from HttpCookie.java
|
||||
private final static String[] COOKIE_DATE_FORMATS = {
|
||||
"EEE',' dd-MMM-yy HH:mm:ss 'GMT'",
|
||||
"EEE',' dd MMM yy HH:mm:ss 'GMT'",
|
||||
"EEE MMM dd yy HH:mm:ss 'GMT'Z",
|
||||
"EEE',' dd-MMM-yyyy HH:mm:ss 'GMT'",
|
||||
"EEE',' dd MMM yyyy HH:mm:ss 'GMT'",
|
||||
"EEE MMM dd yyyy HH:mm:ss 'GMT'Z"
|
||||
};
|
||||
static final TimeZone GMT = TimeZone.getTimeZone("GMT");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Calendar cal = Calendar.getInstance(GMT);
|
||||
|
||||
for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) {
|
||||
SimpleDateFormat df = new SimpleDateFormat(COOKIE_DATE_FORMATS[i],
|
||||
Locale.US);
|
||||
cal.set(1970, 0, 1, 0, 0, 0);
|
||||
df.setTimeZone(GMT);
|
||||
df.setLenient(false);
|
||||
df.set2DigitYearStart(cal.getTime());
|
||||
CookieManager cm = new CookieManager(
|
||||
null, CookiePolicy.ACCEPT_ALL);
|
||||
CookieHandler.setDefault(cm);
|
||||
Map<String,List<String>> header = new HashMap<>();
|
||||
List<String> values = new ArrayList<>();
|
||||
|
||||
cal.set(1970, 6, 9, 10, 10, 1);
|
||||
StringBuilder datestring =
|
||||
new StringBuilder(df.format(cal.getTime()));
|
||||
values.add(
|
||||
"TEST1=TEST1; Path=/; Expires=" + datestring.toString());
|
||||
|
||||
cal.set(1969, 6, 9, 10, 10, 2);
|
||||
datestring = new StringBuilder(df.format(cal.getTime()));
|
||||
values.add(
|
||||
"TEST2=TEST2; Path=/; Expires=" + datestring.toString());
|
||||
|
||||
cal.set(2070, 6, 9, 10, 10, 3);
|
||||
datestring = new StringBuilder(df.format(cal.getTime()));
|
||||
values.add(
|
||||
"TEST3=TEST3; Path=/; Expires=" + datestring.toString());
|
||||
|
||||
cal.set(2069, 6, 9, 10, 10, 4);
|
||||
datestring = new StringBuilder(df.format(cal.getTime()));
|
||||
values.add(
|
||||
"TEST4=TEST4; Path=/; Expires=" + datestring.toString());
|
||||
|
||||
header.put("Set-Cookie", values);
|
||||
URI uri = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.path("/")
|
||||
.buildUnchecked();
|
||||
System.out.println("URI: " + uri);
|
||||
cm.put(uri, header);
|
||||
|
||||
CookieStore cookieJar = cm.getCookieStore();
|
||||
List <HttpCookie> cookies = cookieJar.getCookies();
|
||||
if (COOKIE_DATE_FORMATS[i].contains("yyyy")) {
|
||||
if (cookies.size() != 2)
|
||||
throw new RuntimeException(
|
||||
"Incorrectly parsing a bad date");
|
||||
} else if (cookies.size() != 1) {
|
||||
throw new RuntimeException(
|
||||
"Incorrectly parsing a bad date");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
85
test/jdk/java/net/HttpCookie/IllegalCookieNameTest.java
Normal file
85
test/jdk/java/net/HttpCookie/IllegalCookieNameTest.java
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 7183292
|
||||
* @library /test/lib
|
||||
* @modules jdk.httpserver
|
||||
* @run main IllegalCookieNameTest
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true IllegalCookieNameTest
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import com.sun.net.httpserver.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class IllegalCookieNameTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
HttpServer s = null;
|
||||
try {
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
InetSocketAddress addr = new InetSocketAddress(loopback, 0);
|
||||
s = HttpServer.create(addr, 10);
|
||||
s.createContext("/", new HHandler());
|
||||
s.start();
|
||||
String u = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(s.getAddress().getPort())
|
||||
.path("/")
|
||||
.build().toString();
|
||||
CookieHandler.setDefault(new TestCookieHandler());
|
||||
URL url = new URL(u);
|
||||
HttpURLConnection c = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
|
||||
c.getHeaderFields();
|
||||
System.out.println ("OK");
|
||||
} finally {
|
||||
s.stop(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestCookieHandler extends CookieHandler {
|
||||
@Override
|
||||
public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) {
|
||||
return new HashMap<String, List<String>>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(URI uri, Map<String, List<String>> responseHeaders) {
|
||||
}
|
||||
}
|
||||
|
||||
class HHandler implements HttpHandler {
|
||||
public void handle (HttpExchange e) {
|
||||
try {
|
||||
Headers h = e.getResponseHeaders();
|
||||
h.set ("Set-Cookie", "domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.foo.com");
|
||||
e.sendResponseHeaders(200, -1);
|
||||
e.close();
|
||||
} catch (Exception ex) {
|
||||
System.out.println (ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8351983
|
||||
* @summary HttpCookie Parser Incorrectly Handles Cookies with Expires Attribute
|
||||
* @run testng java.base/java.net.MaxAgeExpires
|
||||
*/
|
||||
public class MaxAgeExpiresDriver {
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
public class MaxAgeExpires {
|
||||
|
||||
static final DateTimeFormatter dtFormatter =
|
||||
DateTimeFormatter.RFC_1123_DATE_TIME;
|
||||
|
||||
static final String NOW_PLUS_500_SEC =
|
||||
dtFormatter.format(ZonedDateTime.ofInstant(Instant.now()
|
||||
.plusSeconds(500), ZoneId.of("UTC")));
|
||||
|
||||
// Test dates 1 minute apart
|
||||
static final String DT1 = "Mon, 01 Jan 2024 01:00:00 GMT";
|
||||
static final String DT2 = "Mon, 01 Jan 2024 01:01:00 GMT";
|
||||
static final String DT3 = "Mon, 01 Jan 2024 01:02:00 GMT";
|
||||
|
||||
static final String FAR_FUTURE = "Mon, 01 Jan 4024 01:02:00 GMT";
|
||||
|
||||
static final ZonedDateTime zdt1 = ZonedDateTime.parse(DT1, dtFormatter);
|
||||
static final ZonedDateTime zdt2 = ZonedDateTime.parse(DT2, dtFormatter);
|
||||
static final ZonedDateTime zdt3 = ZonedDateTime.parse(DT3, dtFormatter);
|
||||
|
||||
static long zdtToMillis(ZonedDateTime zdt) {
|
||||
return zdt.toInstant().getEpochSecond() * 1000; // always exact seconds
|
||||
}
|
||||
|
||||
@DataProvider(name = "testData")
|
||||
public Object[][] testData() {
|
||||
return new Object[][] {
|
||||
// Date string in past. But checking based on current time.
|
||||
{-1L, -1L, -1L, DT1, 0, true},
|
||||
{-1L, -1L, 1000, DT1, 1000, false},
|
||||
{-1L, -1L, 0, DT1, 0, true},
|
||||
{-1L, -1L, 1000, NOW_PLUS_500_SEC, 1000, false},
|
||||
|
||||
// Far in the future. Just check hasExpired() not the exact maxAge
|
||||
{-1L, -1L, -1L, FAR_FUTURE, -1L, false},
|
||||
|
||||
// Tests using fixed creation and verification dates
|
||||
// (independent of current time)
|
||||
// expires=
|
||||
// maxAge= |
|
||||
// create time expiry check time | |expected maxAge
|
||||
// | | | | | hasExpired()
|
||||
// | | | | | | expected
|
||||
{zdtToMillis(zdt1), zdtToMillis(zdt3), -1L, DT2, 60, true},
|
||||
{zdtToMillis(zdt1), zdtToMillis(zdt3), 20, DT2, 20, true},
|
||||
{zdtToMillis(zdt1), zdtToMillis(zdt2), 40, DT3, 40, true},
|
||||
{zdtToMillis(zdt1), zdtToMillis(zdt2), -1L, DT3,120, false}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@Test(dataProvider = "testData")
|
||||
public void test1(long creationInstant, // if -1, then current time is used
|
||||
long expiryCheckInstant, // if -1 then current time is used
|
||||
long maxAge, // if -1, then not included in String
|
||||
String expires, // if null, then not included in String
|
||||
long expectedAge, // expected return value from getMaxAge()
|
||||
boolean hasExpired) // expected return value from hasExpired()
|
||||
throws Exception
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Set-Cookie: name=value");
|
||||
if (expires != null)
|
||||
sb.append("; expires=" + expires);
|
||||
if (maxAge != -1)
|
||||
sb.append("; max-age=" + Long.toString(maxAge));
|
||||
|
||||
String s = sb.toString();
|
||||
System.out.println(s);
|
||||
HttpCookie cookie;
|
||||
if (creationInstant == -1)
|
||||
cookie = HttpCookie.parse(s).get(0);
|
||||
else
|
||||
cookie = HttpCookie.parse(s, false, creationInstant).get(0);
|
||||
|
||||
if (expectedAge != -1 && cookie.getMaxAge() != expectedAge) {
|
||||
System.out.println("getMaxAge returned " + cookie.getMaxAge());
|
||||
System.out.println("expectedAge was " + expectedAge);
|
||||
throw new RuntimeException("Test failed: wrong age");
|
||||
}
|
||||
|
||||
boolean expired = expiryCheckInstant == -1
|
||||
? cookie.hasExpired()
|
||||
: cookie.hasExpired(expiryCheckInstant);
|
||||
|
||||
if (expired != hasExpired) {
|
||||
System.out.println("cookie.hasExpired() returned " + expired);
|
||||
System.out.println("hasExpired was " + hasExpired);
|
||||
System.out.println("getMaxAge() returned " + cookie.getMaxAge());
|
||||
throw new RuntimeException("Test failed: wrong hasExpired");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
// Miscellaneous tests that setMaxAge() overrides whatever was set already
|
||||
HttpCookie cookie = HttpCookie.parse("Set-Cookie: name=value; max-age=100").get(0);
|
||||
Assert.assertEquals(cookie.getMaxAge(), 100);
|
||||
cookie.setMaxAge(200);
|
||||
Assert.assertEquals(cookie.getMaxAge(), 200);
|
||||
cookie.setMaxAge(-2);
|
||||
Assert.assertEquals(cookie.getMaxAge(), -2);
|
||||
}
|
||||
}
|
||||
143
test/jdk/java/net/HttpURLConnection/HostHeaderTest.java
Normal file
143
test/jdk/java/net/HttpURLConnection/HostHeaderTest.java
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8359709
|
||||
* @summary verify that if the Host header is allowed to be set by the application
|
||||
* then the correct value gets set in a HTTP request issued through
|
||||
* java.net.HttpURLConnection
|
||||
* @library /test/lib
|
||||
* @run junit HostHeaderTest
|
||||
* @run junit/othervm -Dsun.net.http.allowRestrictedHeaders=true HostHeaderTest
|
||||
* @run junit/othervm -Dsun.net.http.allowRestrictedHeaders=false HostHeaderTest
|
||||
*/
|
||||
class HostHeaderTest {
|
||||
|
||||
private static final String SERVER_CTX_ROOT = "/8359709/";
|
||||
private static final boolean allowsHostHeader = Boolean.getBoolean("sun.net.http.allowRestrictedHeaders");
|
||||
|
||||
private static HttpServer server;
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() throws Exception {
|
||||
final InetSocketAddress addr = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
|
||||
server = HttpServer.create(addr, 0);
|
||||
server.createContext(SERVER_CTX_ROOT, new Handler());
|
||||
server.start();
|
||||
System.err.println("started server at " + server.getAddress());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void afterAll() throws Exception {
|
||||
if (server != null) {
|
||||
System.err.println("stopping server " + server.getAddress());
|
||||
server.stop(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHostHeader() throws Exception {
|
||||
final InetSocketAddress serverAddr = server.getAddress();
|
||||
final URL reqURL = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(serverAddr.getPort())
|
||||
.path(SERVER_CTX_ROOT)
|
||||
.build().toURL();
|
||||
final URLConnection conn = reqURL.openConnection(Proxy.NO_PROXY);
|
||||
|
||||
conn.setRequestProperty("Host", "foobar");
|
||||
if (!allowsHostHeader) {
|
||||
// if restricted headers aren't allowed to be set by the user, then
|
||||
// we expect the previous call to setRequestProperty to not set the Host
|
||||
// header
|
||||
assertNull(conn.getRequestProperty("Host"), "Host header unexpectedly set");
|
||||
}
|
||||
|
||||
assertInstanceOf(HttpURLConnection.class, conn);
|
||||
final HttpURLConnection httpURLConn = (HttpURLConnection) conn;
|
||||
|
||||
// send the HTTP request
|
||||
System.err.println("sending request " + reqURL);
|
||||
final int respCode = httpURLConn.getResponseCode();
|
||||
assertEquals(200, respCode, "unexpected response code");
|
||||
// verify that the server side handler received the expected
|
||||
// Host header value in the request
|
||||
try (final InputStream is = httpURLConn.getInputStream()) {
|
||||
final byte[] resp = is.readAllBytes();
|
||||
// if Host header wasn't explicitly set, then we expect it to be
|
||||
// derived from the request URL
|
||||
final String expected = allowsHostHeader
|
||||
? "foobar"
|
||||
: reqURL.getHost() + ":" + reqURL.getPort();
|
||||
final String actual = new String(resp, US_ASCII);
|
||||
assertEquals(expected, actual, "unexpected Host header received on server side");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Handler implements HttpHandler {
|
||||
private static final int NO_RESPONSE_BODY = -1;
|
||||
|
||||
@Override
|
||||
public void handle(final HttpExchange exchange) throws IOException {
|
||||
final List<String> headerVals = exchange.getRequestHeaders().get("Host");
|
||||
System.err.println("Host header has value(s): " + headerVals);
|
||||
// unexpected Host header value, respond with 400 status code
|
||||
if (headerVals == null || headerVals.size() != 1) {
|
||||
System.err.println("Unexpected header value(s) for Host header: " + headerVals);
|
||||
exchange.sendResponseHeaders(400, NO_RESPONSE_BODY);
|
||||
return;
|
||||
}
|
||||
// respond back with the Host header value that we found in the request
|
||||
final byte[] response = headerVals.getFirst().getBytes(US_ASCII);
|
||||
exchange.sendResponseHeaders(200, response.length);
|
||||
try (final OutputStream os = exchange.getResponseBody()) {
|
||||
os.write(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
92
test/jdk/java/net/HttpURLConnection/HttpResponseCode.java
Normal file
92
test/jdk/java/net/HttpURLConnection/HttpResponseCode.java
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4473092
|
||||
* @library /test/lib
|
||||
* @summary Method throws IOException when object should be returned
|
||||
* @run main HttpResponseCode
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true HttpResponseCode
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class HttpResponseCode implements Runnable {
|
||||
ServerSocket ss;
|
||||
/*
|
||||
* Our "http" server
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
Socket s = ss.accept();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(s.getInputStream()) );
|
||||
String req = in.readLine();
|
||||
|
||||
PrintStream out = new PrintStream(
|
||||
new BufferedOutputStream(
|
||||
s.getOutputStream() ));
|
||||
|
||||
|
||||
/* send the header */
|
||||
out.print("HTTP/1.1 403 Forbidden\r\n");
|
||||
out.print("\r\n");
|
||||
out.flush();
|
||||
|
||||
s.close();
|
||||
ss.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
HttpResponseCode() throws Exception {
|
||||
/* start the server */
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
(new Thread(this)).start();
|
||||
|
||||
/* establish http connection to server */
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(ss.getLocalPort())
|
||||
.path("/missing.nothtml")
|
||||
.toURL();
|
||||
URLConnection uc = url.openConnection(Proxy.NO_PROXY);
|
||||
int respCode1 = ((HttpURLConnection)uc).getResponseCode();
|
||||
((HttpURLConnection)uc).disconnect();
|
||||
int respCode2 = ((HttpURLConnection)uc).getResponseCode();
|
||||
if (respCode1 != 403 || respCode2 != 403) {
|
||||
throw new RuntimeException("Testing Http response code failed");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
new HttpResponseCode();
|
||||
}
|
||||
}
|
||||
170
test/jdk/java/net/HttpURLConnection/HttpURLConWithProxy.java
Normal file
170
test/jdk/java/net/HttpURLConnection/HttpURLConWithProxy.java
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2024, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8161016 8183369
|
||||
* @library /test/lib
|
||||
* @summary When proxy is set HttpURLConnection should not use DIRECT connection.
|
||||
* @run main/othervm HttpURLConWithProxy
|
||||
*/
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
public class HttpURLConWithProxy {
|
||||
|
||||
private static Logger logger =
|
||||
Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
|
||||
|
||||
public static void main(String... arg) throws Exception {
|
||||
// Remove the default nonProxyHosts to use localhost for testing
|
||||
System.setProperty("http.nonProxyHosts", "");
|
||||
|
||||
// 240.0.0.0/4 is unallocated and "reserved for future use" (RFC 1112, Section 4)
|
||||
System.setProperty("http.proxyHost", "240.0.0.1");
|
||||
System.setProperty("http.proxyPort", "1111");
|
||||
|
||||
// Use the logger to help verify the Proxy was used
|
||||
logger.setLevel(Level.ALL);
|
||||
Handler h = new ProxyHandler();
|
||||
h.setLevel(Level.ALL);
|
||||
logger.addHandler(h);
|
||||
|
||||
ServerSocket ss;
|
||||
URL url;
|
||||
HttpURLConnection con;
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
InetSocketAddress address = new InetSocketAddress(loopback, 0);
|
||||
|
||||
// Test1: using Proxy set by System Property:
|
||||
try {
|
||||
ss = new ServerSocket();
|
||||
ss.bind(address);
|
||||
url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(ss.getLocalPort())
|
||||
.toURL();
|
||||
con = (HttpURLConnection) url.openConnection();
|
||||
con.setConnectTimeout(10 * 1000);
|
||||
con.connect();
|
||||
if(con.usingProxy()){
|
||||
System.out.println("Test1 Passed with: Connection succeeded with proxy");
|
||||
} else {
|
||||
throw new RuntimeException("Shouldn't use DIRECT connection "
|
||||
+ "when proxy is invalid/down");
|
||||
}
|
||||
} catch (IOException ie) {
|
||||
if(!ProxyHandler.proxyRetried) {
|
||||
throw new RuntimeException("Connection not retried with proxy");
|
||||
}
|
||||
System.out.println("Test1 Passed with: " + ie.getMessage());
|
||||
}
|
||||
|
||||
// Test2: using custom ProxySelector implementation
|
||||
ProxyHandler.proxyRetried = false;
|
||||
MyProxySelector myProxySel = new MyProxySelector();
|
||||
ProxySelector.setDefault(myProxySel);
|
||||
try {
|
||||
ss = new ServerSocket();
|
||||
ss.bind(address);
|
||||
url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(ss.getLocalPort())
|
||||
.toURL();
|
||||
con = (HttpURLConnection) url.openConnection();
|
||||
con.setConnectTimeout(10 * 1000);
|
||||
con.connect();
|
||||
if(con.usingProxy()){
|
||||
System.out.println("Test2 Passed with: Connection succeeded with proxy");
|
||||
} else {
|
||||
throw new RuntimeException("Shouldn't use DIRECT connection "
|
||||
+ "when proxy is invalid/down");
|
||||
}
|
||||
} catch (IOException ie) {
|
||||
if(!ProxyHandler.proxyRetried) {
|
||||
throw new RuntimeException("Connection not retried with proxy");
|
||||
}
|
||||
System.out.println("Test2 Passed with: " + ie.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MyProxySelector extends ProxySelector {
|
||||
|
||||
List<Proxy> proxies = new ArrayList<>();
|
||||
|
||||
MyProxySelector() {
|
||||
// 240.0.0.0/4 is unallocated and "reserved for future use" (RFC 1112, Section 4)
|
||||
Proxy p1 = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("240.0.0.2", 2222));
|
||||
Proxy p2 = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("240.0.0.3", 3333));
|
||||
proxies.add(p1);
|
||||
proxies.add(p2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Proxy> select(URI uri) {
|
||||
return proxies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
|
||||
// System.out.println("MyProxySelector.connectFailed(): "+sa);
|
||||
}
|
||||
}
|
||||
|
||||
class ProxyHandler extends Handler {
|
||||
public static boolean proxyRetried = false;
|
||||
|
||||
@Override
|
||||
public void publish(LogRecord record) {
|
||||
if (record.getMessage().contains("Retrying with proxy")) {
|
||||
proxyRetried = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
335
test/jdk/java/net/HttpURLConnection/HttpURLConnUsingProxy.java
Normal file
335
test/jdk/java/net/HttpURLConnection/HttpURLConnUsingProxy.java
Normal file
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8231632
|
||||
* @summary HttpURLConnection::usingProxy could specify that it lazily evaluates the fact
|
||||
* @modules java.base/sun.net.www
|
||||
* @library /test/lib
|
||||
* @run main/othervm HttpURLConnUsingProxy
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class HttpURLConnUsingProxy {
|
||||
static HttpServer server;
|
||||
static Proxy proxy;
|
||||
static InetSocketAddress isa;
|
||||
|
||||
static class Handler implements HttpHandler {
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
byte[] response = "Hello World!".getBytes(StandardCharsets.UTF_8);
|
||||
try (InputStream req = exchange.getRequestBody()) {
|
||||
req.readAllBytes();
|
||||
}
|
||||
exchange.sendResponseHeaders(200, response.length);
|
||||
try (OutputStream resp = exchange.getResponseBody()) {
|
||||
resp.write(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
|
||||
InetSocketAddress addr = new InetSocketAddress(loopbackAddress, 0);
|
||||
server = HttpServer.create(addr, 0);
|
||||
server.createContext("/HttpURLConnUsingProxy/http1/", new Handler());
|
||||
server.start();
|
||||
|
||||
ProxyServer pserver = new ProxyServer(loopbackAddress,
|
||||
server.getAddress().getPort());
|
||||
// Start proxy server
|
||||
new Thread(pserver).start();
|
||||
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(server.getAddress().getPort())
|
||||
.path("/HttpURLConnUsingProxy/http1/x.html")
|
||||
.toURLUnchecked();
|
||||
|
||||
// NO_PROXY
|
||||
try {
|
||||
HttpURLConnection urlc =
|
||||
(HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
|
||||
assertEqual(urlc.usingProxy(), false);
|
||||
urlc.getResponseCode();
|
||||
assertEqual(urlc.usingProxy(), false);
|
||||
urlc.disconnect();
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Direct connection should succeed: "
|
||||
+ ioe.getMessage());
|
||||
}
|
||||
|
||||
// Non-existing proxy
|
||||
try {
|
||||
isa = InetSocketAddress.createUnresolved("inexistent", 8080);
|
||||
proxy = new Proxy(Proxy.Type.HTTP, isa);
|
||||
HttpURLConnection urlc = (HttpURLConnection) url.openConnection(proxy);
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
InputStream is = urlc.getInputStream();
|
||||
is.close();
|
||||
throw new RuntimeException("Non-existing proxy should cause IOException");
|
||||
} catch (IOException ioe) {
|
||||
// expected
|
||||
}
|
||||
|
||||
// Normal proxy settings
|
||||
try {
|
||||
isa = InetSocketAddress.createUnresolved(loopbackAddress.getHostAddress(),
|
||||
pserver.getPort());
|
||||
proxy = new Proxy(Proxy.Type.HTTP, isa);
|
||||
HttpURLConnection urlc = (HttpURLConnection) url.openConnection(proxy);
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
urlc.getResponseCode();
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
urlc.disconnect();
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Connection through local proxy should succeed: "
|
||||
+ ioe.getMessage());
|
||||
}
|
||||
|
||||
// Reuse proxy with new HttpURLConnection
|
||||
try {
|
||||
HttpURLConnection urlc = (HttpURLConnection) url.openConnection(proxy);
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
urlc.getResponseCode();
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
read(urlc.getInputStream());
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Connection through local proxy should succeed: "
|
||||
+ ioe.getMessage());
|
||||
}
|
||||
|
||||
// Reuse proxy with existing HttpURLConnection
|
||||
try {
|
||||
HttpURLConnection urlc = (HttpURLConnection) url.openConnection(proxy);
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
urlc.getResponseCode();
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
read(urlc.getInputStream());
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
urlc.disconnect();
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Connection through local proxy should succeed: "
|
||||
+ ioe.getMessage());
|
||||
}
|
||||
|
||||
// ProxySelector with normal proxy settings
|
||||
try {
|
||||
ProxySelector.setDefault(ProxySelector.of(isa));
|
||||
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
|
||||
assertEqual(urlc.usingProxy(), false);
|
||||
urlc.getResponseCode();
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
read(urlc.getInputStream());
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
urlc.disconnect();
|
||||
assertEqual(urlc.usingProxy(), true);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Connection through local proxy should succeed: "
|
||||
+ ioe.getMessage());
|
||||
}
|
||||
|
||||
// ProxySelector with proxying disabled
|
||||
try {
|
||||
ProxySelector.setDefault(ProxySelector.of(null));
|
||||
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
|
||||
assertEqual(urlc.usingProxy(), false);
|
||||
urlc.getResponseCode();
|
||||
assertEqual(urlc.usingProxy(), false);
|
||||
read(urlc.getInputStream());
|
||||
assertEqual(urlc.usingProxy(), false);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Direct connection should succeed: "
|
||||
+ ioe.getMessage());
|
||||
}
|
||||
|
||||
// ProxySelector overwritten
|
||||
try {
|
||||
ProxySelector.setDefault(ProxySelector.of(isa));
|
||||
HttpURLConnection urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
|
||||
assertEqual(urlc.usingProxy(), false);
|
||||
urlc.disconnect();
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("Direct connection should succeed: "
|
||||
+ ioe.getMessage());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (server != null) {
|
||||
server.stop(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ProxyServer extends Thread {
|
||||
private static ServerSocket ss = null;
|
||||
|
||||
// Client requesting a tunnel
|
||||
private Socket clientSocket = null;
|
||||
|
||||
/*
|
||||
* Origin server's address and port that the client
|
||||
* wants to establish the tunnel for communication.
|
||||
*/
|
||||
private InetAddress serverInetAddr;
|
||||
private int serverPort;
|
||||
|
||||
public ProxyServer(InetAddress server, int port) throws IOException {
|
||||
serverInetAddr = server;
|
||||
serverPort = port;
|
||||
ss = new ServerSocket(0, 0, InetAddress.getLoopbackAddress());
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
clientSocket = ss.accept();
|
||||
processRequests();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Proxy failed: " + e);
|
||||
e.printStackTrace();
|
||||
try {
|
||||
ss.close();
|
||||
} catch (IOException ioe) {
|
||||
System.out.println("ProxyServer close error: " + ioe);
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processRequests() throws Exception {
|
||||
// Connection set to tunneling mode
|
||||
|
||||
Socket serverSocket = new Socket(serverInetAddr, serverPort);
|
||||
ProxyTunnel clientToServer = new ProxyTunnel(
|
||||
clientSocket, serverSocket);
|
||||
ProxyTunnel serverToClient = new ProxyTunnel(
|
||||
serverSocket, clientSocket);
|
||||
clientToServer.start();
|
||||
serverToClient.start();
|
||||
System.out.println("Proxy: Started tunneling...");
|
||||
|
||||
clientToServer.join();
|
||||
serverToClient.join();
|
||||
System.out.println("Proxy: Finished tunneling...");
|
||||
|
||||
clientToServer.close();
|
||||
serverToClient.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* **************************************************************
|
||||
* Helper methods follow
|
||||
* **************************************************************
|
||||
*/
|
||||
public int getPort() {
|
||||
return ss.getLocalPort();
|
||||
}
|
||||
|
||||
/*
|
||||
* This inner class provides unidirectional data flow through the sockets
|
||||
* by continuously copying bytes from input socket to output socket
|
||||
* while both sockets are open and EOF has not been received.
|
||||
*/
|
||||
static class ProxyTunnel extends Thread {
|
||||
Socket sockIn;
|
||||
Socket sockOut;
|
||||
InputStream input;
|
||||
OutputStream output;
|
||||
|
||||
public ProxyTunnel(Socket sockIn, Socket sockOut) throws Exception {
|
||||
this.sockIn = sockIn;
|
||||
this.sockOut = sockOut;
|
||||
input = sockIn.getInputStream();
|
||||
output = sockOut.getOutputStream();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int BUFFER_SIZE = 400;
|
||||
byte[] buf = new byte[BUFFER_SIZE];
|
||||
int bytesRead = 0;
|
||||
int count = 0; // Keep track of amount of data transferred
|
||||
|
||||
try {
|
||||
while ((bytesRead = input.read(buf)) >= 0) {
|
||||
output.write(buf, 0, bytesRead);
|
||||
output.flush();
|
||||
count += bytesRead;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
/*
|
||||
* Peer end has closed connection
|
||||
* so we close tunnel
|
||||
*/
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
if (!sockIn.isClosed())
|
||||
sockIn.close();
|
||||
if (!sockOut.isClosed())
|
||||
sockOut.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertEqual(boolean usingProxy, boolean expected) {
|
||||
if (usingProxy != expected) {
|
||||
throw new RuntimeException("Expected: " + expected
|
||||
+ " but usingProxy returned: " + usingProxy);
|
||||
}
|
||||
}
|
||||
|
||||
private static String read(InputStream inputStream) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BufferedReader bufferedReader = new BufferedReader(
|
||||
new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||
int i = bufferedReader.read();
|
||||
while (i != -1) {
|
||||
sb.append((char) i);
|
||||
i = bufferedReader.read();
|
||||
}
|
||||
bufferedReader.close();
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 2024, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8314978
|
||||
* @summary Multiple server call from connection failing with expect100 in
|
||||
* getOutputStream
|
||||
* @library /test/lib
|
||||
* @run junit/othervm HttpURLConnectionExpect100Test
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
import java.net.HttpURLConnection;
|
||||
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class HttpURLConnectionExpect100Test {
|
||||
|
||||
private HttpServer server;
|
||||
private int port;
|
||||
static final String RESPONSE = "This is default response.";
|
||||
|
||||
@BeforeAll
|
||||
void setup() throws Exception {
|
||||
server = HttpServer.create();
|
||||
port = server.getPort();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
void teardown() throws Exception {
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expect100ContinueHitCountTest() throws Exception {
|
||||
server.resetHitCount();
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(port)
|
||||
.toURL();
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("PUT");
|
||||
//send expect continue
|
||||
conn.setRequestProperty("Expect", "100-continue");
|
||||
sendRequest(conn);
|
||||
getHeaderField(conn);
|
||||
// Server rejects the expect 100-continue request with 417 response
|
||||
assertEquals(417, conn.getResponseCode());
|
||||
assertEquals(1, server.getServerHitCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultRequestHitCountTest() throws Exception {
|
||||
server.resetHitCount();
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(port)
|
||||
.toURL();
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("PUT");
|
||||
sendRequest(conn);
|
||||
getHeaderField(conn);
|
||||
assertEquals(200, conn.getResponseCode());
|
||||
try ( InputStream in = conn.getInputStream()) {
|
||||
byte[] data = in.readAllBytes();
|
||||
assertEquals(RESPONSE.length(), data.length);
|
||||
}
|
||||
assertEquals(1, server.getServerHitCount());
|
||||
}
|
||||
|
||||
private void sendRequest(final HttpURLConnection conn) throws Exception {
|
||||
conn.setDoOutput(true);
|
||||
conn.setFixedLengthStreamingMode(10);
|
||||
byte[] payload = new byte[10];
|
||||
try ( OutputStream os = conn.getOutputStream()) {
|
||||
os.write(payload);
|
||||
os.flush();
|
||||
} catch (IOException e) {
|
||||
// intentional, server will reject the expect 100
|
||||
System.err.println("Got expected exception: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private void getHeaderField(final HttpURLConnection conn) {
|
||||
// Call getHeaderFiels in loop, this should not hit server.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
System.out.println("Getting: field" + i);
|
||||
conn.getHeaderField("field" + i);
|
||||
}
|
||||
}
|
||||
|
||||
static class HttpServer extends Thread {
|
||||
|
||||
private final ServerSocket ss;
|
||||
private static HttpServer inst;
|
||||
private volatile int hitCount;
|
||||
private volatile boolean isRunning;
|
||||
private final int port;
|
||||
|
||||
private HttpServer() throws IOException {
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
port = ss.getLocalPort();
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
static HttpServer create() throws IOException {
|
||||
if (inst != null) {
|
||||
return inst;
|
||||
} else {
|
||||
inst = new HttpServer();
|
||||
inst.setDaemon(true);
|
||||
inst.start();
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
|
||||
int getServerHitCount() {
|
||||
return hitCount;
|
||||
}
|
||||
|
||||
void resetHitCount() {
|
||||
hitCount = 0;
|
||||
}
|
||||
|
||||
int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
void close() {
|
||||
isRunning = false;
|
||||
if (ss != null && !ss.isClosed()) {
|
||||
try {
|
||||
ss.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Socket client;
|
||||
try (ss) {
|
||||
while (isRunning) {
|
||||
client = ss.accept();
|
||||
System.out.println(client.getRemoteSocketAddress().toString());
|
||||
hitCount++;
|
||||
handleConnection(client);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// throw exception only if isRunning is true
|
||||
if (isRunning) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleConnection(Socket client) throws IOException {
|
||||
try (client; BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(client.getInputStream()));
|
||||
PrintStream out = new PrintStream(client.getOutputStream())) {
|
||||
handle_connection(in, out);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private void handle_connection(BufferedReader in, PrintStream out)
|
||||
throws IOException, InterruptedException {
|
||||
StringBuilder clientRequest = new StringBuilder();
|
||||
String line = null;
|
||||
do {
|
||||
line = in.readLine();
|
||||
clientRequest.append(line);
|
||||
} while (line != null && line.length() != 0);
|
||||
if (clientRequest.toString().contains("100-continue")) {
|
||||
rejectExpect100Continue(out);
|
||||
} else {
|
||||
defaultResponse(out);
|
||||
}
|
||||
// wait until the client closes the socket
|
||||
while (line != null) {
|
||||
line = in.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
private void rejectExpect100Continue(PrintStream out) {
|
||||
out.print("HTTP/1.1 417 Expectation Failed\r\n");
|
||||
out.print("Server: Test-Server\r\n");
|
||||
out.print("Connection: close\r\n");
|
||||
out.print("Content-Length: 0\r\n");
|
||||
out.print("\r\n");
|
||||
out.flush();
|
||||
}
|
||||
|
||||
private void defaultResponse(PrintStream out) {
|
||||
// send the 200 OK
|
||||
out.print("HTTP/1.1 200 OK\r\n");
|
||||
out.print("Server: Test-Server\r\n");
|
||||
out.print("Connection: close\r\n");
|
||||
out.print("Content-Length: " + RESPONSE.length() + "\r\n\r\n");
|
||||
out.print(RESPONSE);
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,443 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8054022
|
||||
* @summary Verify that expect 100-continue doesn't hang
|
||||
* @library /test/lib
|
||||
* @run junit/othervm HttpURLConnectionExpectContinueTest
|
||||
* @run junit/othervm -Djava.net.preferIPv4Stack=true HttpURLConnectionExpectContinueTest
|
||||
* @run junit/othervm -Djava.net.preferIPv6Addresses=true HttpURLConnectionExpectContinueTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class HttpURLConnectionExpectContinueTest {
|
||||
|
||||
class Control {
|
||||
volatile ServerSocket serverSocket = null;
|
||||
volatile boolean stop = false;
|
||||
volatile boolean respondWith100Continue = false;
|
||||
volatile boolean write100ContinueTwice = false;
|
||||
volatile String response = null;
|
||||
}
|
||||
|
||||
private Thread serverThread = null;
|
||||
private volatile Control control;
|
||||
static final Logger logger;
|
||||
|
||||
static {
|
||||
logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
|
||||
logger.setLevel(Level.ALL);
|
||||
Logger.getLogger("").getHandlers()[0].setLevel(Level.ALL);
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public void startServerSocket() throws Exception {
|
||||
Control control = this.control = new Control();
|
||||
|
||||
control.serverSocket = new ServerSocket();
|
||||
control.serverSocket.setReuseAddress(true);
|
||||
control.serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
|
||||
Runnable runnable = () -> {
|
||||
while (!control.stop) {
|
||||
try {
|
||||
Socket socket = control.serverSocket.accept();
|
||||
InputStream inputStream = socket.getInputStream();
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
// Read initial request
|
||||
byte b;
|
||||
while (true) {
|
||||
b = (byte) inputStreamReader.read();
|
||||
stringBuilder.append((char) b);
|
||||
|
||||
if (stringBuilder.length() >= 4) {
|
||||
char[] lastBytes = new char[4];
|
||||
stringBuilder.getChars(
|
||||
stringBuilder.length() - 4,
|
||||
stringBuilder.length(), lastBytes, 0);
|
||||
if (Arrays.equals(lastBytes, new char[]{'\r', '\n', '\r', '\n'})) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OutputStream outputStream = socket.getOutputStream();
|
||||
|
||||
String header = stringBuilder.toString();
|
||||
String contentLengthString = "Content-Length:";
|
||||
|
||||
// send 100 continue responses if set by test
|
||||
if (control.respondWith100Continue) {
|
||||
outputStream.write("HTTP/1.1 100 Continue\r\n\r\n".getBytes());
|
||||
outputStream.flush();
|
||||
if (control.write100ContinueTwice) {
|
||||
outputStream.write("HTTP/1.1 100 Continue\r\n\r\n".getBytes());
|
||||
outputStream.flush();
|
||||
}
|
||||
}
|
||||
|
||||
// expect main request to be received
|
||||
int idx = header.indexOf(contentLengthString);
|
||||
|
||||
if (idx >= 0) {
|
||||
String substr = header.substring(idx + contentLengthString.length());
|
||||
idx = substr.indexOf('\r');
|
||||
substr = substr.substring(0, idx);
|
||||
int contentLength = Integer.parseInt(substr.trim());
|
||||
|
||||
StringBuilder contentLengthBuilder = new StringBuilder();
|
||||
for (int i = 0; i < contentLength; i++) {
|
||||
b = (byte) inputStreamReader.read();
|
||||
contentLengthBuilder.append((char) b);
|
||||
}
|
||||
|
||||
} else {
|
||||
StringBuilder contentLengthBuilder = new StringBuilder();
|
||||
while (true) {
|
||||
b = (byte) inputStreamReader.read();
|
||||
contentLengthBuilder.append((char) b);
|
||||
|
||||
if (contentLengthBuilder.length() >= 2) {
|
||||
char[] lastBytes = new char[2];
|
||||
contentLengthBuilder.getChars(
|
||||
contentLengthBuilder.length() - 2,
|
||||
contentLengthBuilder.length(), lastBytes, 0);
|
||||
if (Arrays.equals(lastBytes, new char[]{'\r', '\n'})) {
|
||||
String lengthInHex =
|
||||
contentLengthBuilder.substring(0, contentLengthBuilder.length() - 2);
|
||||
|
||||
int contentLength = Integer.parseInt(lengthInHex, 16);
|
||||
char[] body = new char[contentLength];
|
||||
inputStreamReader.read(body);
|
||||
break;
|
||||
// normally we have to parse more data,
|
||||
// but for simplicity we expect no more chunks...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send response
|
||||
outputStream.write(control.response.getBytes());
|
||||
outputStream.flush();
|
||||
} catch (SocketException e) {
|
||||
// ignore
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
serverThread = new Thread(runnable);
|
||||
serverThread.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public void stopServerSocket() throws Exception {
|
||||
Control control = this.control;
|
||||
control.stop = true;
|
||||
control.serverSocket.close();
|
||||
serverThread.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonChunkedRequestAndNoExpect100ContinueResponse() throws Exception {
|
||||
String body = "testNonChunkedRequestAndNoExpect100ContinueResponse";
|
||||
Control control = this.control;
|
||||
control.response = "HTTP/1.1 200 OK\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n";
|
||||
control.respondWith100Continue = false;
|
||||
control.write100ContinueTwice = false;
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
|
||||
System.err.println("response body: " + responseBody);
|
||||
assertTrue(responseCode == 200,
|
||||
String.format("Expected 200 response, instead received %s", responseCode));
|
||||
assertTrue(body.equals(responseBody),
|
||||
String.format("Expected response %s, instead received %s", body, responseBody));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonChunkedRequestWithExpect100ContinueResponse() throws Exception {
|
||||
String body = "testNonChunkedRequestWithExpect100ContinueResponse";
|
||||
Control control = this.control;
|
||||
control.response = "HTTP/1.1 200 OK\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n";
|
||||
control.respondWith100Continue = true;
|
||||
control.write100ContinueTwice = false;
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
|
||||
System.err.println("response body: " + responseBody);
|
||||
assertTrue(responseCode == 200,
|
||||
String.format("Expected 200 response, instead received %s", responseCode));
|
||||
assertTrue(body.equals(responseBody),
|
||||
String.format("Expected response %s, instead received %s", body, responseBody));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonChunkedRequestWithDoubleExpect100ContinueResponse() throws Exception {
|
||||
String body = "testNonChunkedRequestWithDoubleExpect100ContinueResponse";
|
||||
Control control = this.control;
|
||||
control.response = "HTTP/1.1 200 OK\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n";
|
||||
control.respondWith100Continue = true;
|
||||
control.write100ContinueTwice = true;
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
|
||||
System.err.println("response body: " + responseBody);
|
||||
assertTrue(responseCode == 200,
|
||||
String.format("Expected 200 response, instead received %s", responseCode));
|
||||
assertTrue(body.equals(responseBody),
|
||||
String.format("Expected response %s, instead received %s", body, responseBody));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkedRequestAndNoExpect100ContinueResponse() throws Exception {
|
||||
String body = "testChunkedRequestAndNoExpect100ContinueResponse";
|
||||
Control control = this.control;
|
||||
control.response = "HTTP/1.1 200 OK\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n";
|
||||
control.respondWith100Continue = false;
|
||||
control.write100ContinueTwice = false;
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
connection.setChunkedStreamingMode(body.length() / 2);
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
|
||||
System.err.println("response body: " + responseBody);
|
||||
assertTrue(responseCode == 200,
|
||||
String.format("Expected 200 response, instead received %s", responseCode));
|
||||
assertTrue(body.equals(responseBody),
|
||||
String.format("Expected response %s, instead received %s", body, responseBody));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkedRequestWithExpect100ContinueResponse() throws Exception {
|
||||
String body = "testChunkedRequestWithExpect100ContinueResponse";
|
||||
Control control = this.control;
|
||||
control.response = "HTTP/1.1 200 OK\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n";
|
||||
control.respondWith100Continue = true;
|
||||
control.write100ContinueTwice = false;
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
connection.setChunkedStreamingMode(body.length() / 2);
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
|
||||
System.err.println("response body: " + responseBody);
|
||||
assertTrue(responseCode == 200,
|
||||
String.format("Expected 200 response, instead received %s", responseCode));
|
||||
assertTrue(body.equals(responseBody),
|
||||
String.format("Expected response %s, instead received %s", body, responseBody));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkedRequestWithDoubleExpect100ContinueResponse() throws Exception {
|
||||
String body = "testChunkedRequestWithDoubleExpect100ContinueResponse";
|
||||
Control control = this.control;
|
||||
control.response = "HTTP/1.1 200 OK\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n";
|
||||
control.respondWith100Continue = true;
|
||||
control.write100ContinueTwice = true;
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
connection.setChunkedStreamingMode(body.length() / 2);
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
|
||||
System.err.println("response body: " + responseBody);
|
||||
assertTrue(responseCode == 200,
|
||||
String.format("Expected 200 response, instead received %s", responseCode));
|
||||
assertTrue(body.equals(responseBody),
|
||||
String.format("Expected response %s, instead received %s", body, responseBody));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixedLengthRequestAndNoExpect100ContinueResponse() throws Exception {
|
||||
String body = "testFixedLengthRequestAndNoExpect100ContinueResponse";
|
||||
Control control = this.control;
|
||||
control.response = "HTTP/1.1 200 OK\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n";
|
||||
control.respondWith100Continue = false;
|
||||
control.write100ContinueTwice = false;
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
connection.setFixedLengthStreamingMode(body.length());
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
|
||||
System.err.println("response body: " + responseBody);
|
||||
assertTrue(responseCode == 200,
|
||||
String.format("Expected 200 response, instead received %s", responseCode));
|
||||
assertTrue(body.equals(responseBody),
|
||||
String.format("Expected response %s, instead received %s", body, responseBody));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixedLengthRequestWithExpect100ContinueResponse() throws Exception {
|
||||
String body = "testFixedLengthRequestWithExpect100ContinueResponse";
|
||||
Control control = this.control;
|
||||
control.response = "HTTP/1.1 200 OK\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n";
|
||||
control.respondWith100Continue = true;
|
||||
control.write100ContinueTwice = false;
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
connection.setFixedLengthStreamingMode(body.getBytes().length);
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
|
||||
System.err.println("response body: " + responseBody);
|
||||
assertTrue(responseCode == 200,
|
||||
String.format("Expected 200 response, instead received %s", responseCode));
|
||||
assertTrue(body.equals(responseBody),
|
||||
String.format("Expected response %s, instead received %s", body, responseBody));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixedLengthRequestWithDoubleExpect100ContinueResponse() throws Exception {
|
||||
String body = "testFixedLengthRequestWithDoubleExpect100ContinueResponse";
|
||||
Control control = this.control;
|
||||
control.response = "HTTP/1.1 200 OK\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n";
|
||||
control.respondWith100Continue = true;
|
||||
control.write100ContinueTwice = true;
|
||||
|
||||
HttpURLConnection connection = createConnection();
|
||||
connection.setFixedLengthStreamingMode(body.getBytes().length);
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
|
||||
System.err.println("response body: " + responseBody);
|
||||
assertTrue(responseCode == 200,
|
||||
String.format("Expected 200 response, instead received %s", responseCode));
|
||||
assertTrue(body.equals(responseBody),
|
||||
String.format("Expected response %s, instead received %s", body, responseBody));
|
||||
}
|
||||
|
||||
// Creates a connection with all the common settings used in each test
|
||||
private HttpURLConnection createConnection() throws Exception {
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(control.serverSocket.getLocalPort())
|
||||
.toURL();
|
||||
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
|
||||
connection.setDoOutput(true);
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setUseCaches(false);
|
||||
connection.setInstanceFollowRedirects(false);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Connection", "Close");
|
||||
connection.setRequestProperty("Expect", "100-Continue");
|
||||
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8133686
|
||||
* @summary Ensuring that multiple header values for a given field-name are returned in
|
||||
* the order they were added for HttpURLConnection.getRequestProperties
|
||||
* and HttpURLConnection.getHeaderFields
|
||||
* @library /test/lib
|
||||
* @run testng HttpURLConnectionHeadersOrder
|
||||
*/
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class HttpURLConnectionHeadersOrder {
|
||||
private static final String LOCAL_TEST_ENDPOINT = "/headertest";
|
||||
private static final String ERROR_MESSAGE_TEMPLATE = "Expected Request Properties = %s, Actual Request Properties = %s";
|
||||
private static final List<String> EXPECTED_HEADER_VALUES = Arrays.asList("a", "b", "c");
|
||||
private static HttpServer server;
|
||||
private static URL serverUrl;
|
||||
|
||||
|
||||
@BeforeTest
|
||||
public void beforeTest() throws Exception {
|
||||
SimpleHandler handler = new SimpleHandler();
|
||||
server = createSimpleHttpServer(handler);
|
||||
serverUrl = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.host(server.getAddress().getAddress())
|
||||
.port(server.getAddress().getPort())
|
||||
.path(LOCAL_TEST_ENDPOINT)
|
||||
.toURL();
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void afterTest() {
|
||||
if (server != null)
|
||||
server.stop(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* - This tests requestProperty insertion-order
|
||||
* - on the client side by sending a HTTP GET
|
||||
* - request to a "dummy" server with additional
|
||||
* - custom request properties
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test (priority = 1)
|
||||
public void testRequestPropertiesOrder() throws Exception {
|
||||
final var conn = (HttpURLConnection) serverUrl.openConnection();
|
||||
|
||||
conn.addRequestProperty("test_req_prop", "a");
|
||||
conn.addRequestProperty("test_req_prop", "b");
|
||||
conn.addRequestProperty("test_req_prop", "c");
|
||||
|
||||
conn.setRequestMethod("GET");
|
||||
|
||||
var requestProperties = conn.getRequestProperties();
|
||||
var customRequestProps = requestProperties.get("test_req_prop");
|
||||
|
||||
conn.disconnect();
|
||||
Assert.assertNotNull(customRequestProps);
|
||||
Assert.assertEquals(customRequestProps, EXPECTED_HEADER_VALUES, String.format(ERROR_MESSAGE_TEMPLATE, EXPECTED_HEADER_VALUES.toString(), customRequestProps.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* - This tests whether or not the insertion order is preserved for custom headers
|
||||
* - on the server's side.
|
||||
* - The server will return a custom status code (999) if the expected headers
|
||||
* - are not equal to the actual headers
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test (priority = 2)
|
||||
public void testServerSideRequestHeadersOrder() throws Exception {
|
||||
final var conn = (HttpURLConnection) serverUrl.openConnection();
|
||||
conn.addRequestProperty("test_server_handling", "a");
|
||||
conn.addRequestProperty("test_server_handling", "b");
|
||||
conn.addRequestProperty("test_server_handling", "c");
|
||||
|
||||
int statusCode = conn.getResponseCode();
|
||||
conn.disconnect();
|
||||
Assert.assertEquals(statusCode, 999, "The insertion-order was not preserved on the server-side response headers handling");
|
||||
}
|
||||
|
||||
@Test (priority = 3)
|
||||
public void testClientSideResponseHeadersOrder() throws Exception {
|
||||
final var conn = (HttpURLConnection) serverUrl.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
|
||||
var actualCustomResponseHeaders = conn.getHeaderFields().get("Test_response");
|
||||
Assert.assertNotNull(actualCustomResponseHeaders, "Error in reading custom response headers");
|
||||
Assert.assertEquals(EXPECTED_HEADER_VALUES, actualCustomResponseHeaders, String.format(ERROR_MESSAGE_TEMPLATE, EXPECTED_HEADER_VALUES.toString(), actualCustomResponseHeaders.toString()));
|
||||
}
|
||||
|
||||
private static HttpServer createSimpleHttpServer(SimpleHandler handler) throws IOException {
|
||||
var serverAddress = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
|
||||
var server = HttpServer.create(serverAddress, 0);
|
||||
server.createContext(LOCAL_TEST_ENDPOINT, handler);
|
||||
server.start();
|
||||
System.out.println("Server started on " + server.getAddress());
|
||||
return server;
|
||||
}
|
||||
|
||||
private static class SimpleHandler implements HttpHandler {
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
int statusCode = testRequestHeadersOrder(exchange);
|
||||
sendCustomResponse(exchange, statusCode);
|
||||
}
|
||||
|
||||
private int testRequestHeadersOrder(HttpExchange exchange) {
|
||||
var requestHeaders = exchange.getRequestHeaders();
|
||||
var actualTestRequestHeaders = requestHeaders.get("test_server_handling");
|
||||
|
||||
if (actualTestRequestHeaders == null) {
|
||||
System.out.println("Error: requestHeaders.get(\"test_server_handling\") returned null");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!actualTestRequestHeaders.equals(EXPECTED_HEADER_VALUES)) {
|
||||
System.out.println("Error: " + String.format(ERROR_MESSAGE_TEMPLATE, EXPECTED_HEADER_VALUES.toString(), actualTestRequestHeaders.toString()));
|
||||
return -1;
|
||||
}
|
||||
return 999;
|
||||
}
|
||||
|
||||
private void sendCustomResponse(HttpExchange exchange, int statusCode) throws IOException {
|
||||
var responseHeaders = exchange.getResponseHeaders();
|
||||
responseHeaders.add("test_response", "a");
|
||||
responseHeaders.add("test_response", "b");
|
||||
responseHeaders.add("test_response", "c");
|
||||
|
||||
var outputStream = exchange.getResponseBody();
|
||||
var response = "Testing headers";
|
||||
exchange.sendResponseHeaders(statusCode, response.length());
|
||||
|
||||
outputStream.write(response.getBytes());
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
import sun.net.spi.DefaultProxySelector;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6563286 6797318 8177648 8230220
|
||||
* @summary Tests that sun.net.www.protocol.http.HttpURLConnection when dealing with
|
||||
* sun.net.spi.DefaultProxySelector#select() handles any IllegalArgumentException
|
||||
* correctly
|
||||
* @library /test/lib
|
||||
* @run testng HttpURLProxySelectionTest
|
||||
* @modules java.base/sun.net.spi:+open
|
||||
*/
|
||||
public class HttpURLProxySelectionTest {
|
||||
|
||||
private static final String WEB_APP_CONTEXT = "/httpurlproxytest";
|
||||
|
||||
private HttpServer server;
|
||||
private SimpleHandler handler;
|
||||
private ProxySelector previousDefault;
|
||||
private CustomProxySelector ourProxySelector = new CustomProxySelector();
|
||||
|
||||
@BeforeTest
|
||||
public void beforeTest() throws Exception {
|
||||
previousDefault = ProxySelector.getDefault();
|
||||
ProxySelector.setDefault(ourProxySelector);
|
||||
handler = new SimpleHandler();
|
||||
server = createServer(handler);
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void afterTest() {
|
||||
try {
|
||||
if (server != null) {
|
||||
final int delaySeconds = 0;
|
||||
server.stop(delaySeconds);
|
||||
}
|
||||
} finally {
|
||||
ProxySelector.setDefault(previousDefault);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* - Test initiates a HTTP request to server
|
||||
* - Server receives request and sends a 301 redirect to an URI which doesn't have a "host"
|
||||
* - Redirect is expected to fail with IOException (caused by IllegalArgumentException from DefaultProxySelector)
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
final URL targetURL = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.host(server.getAddress().getAddress())
|
||||
.port(server.getAddress().getPort())
|
||||
.path(WEB_APP_CONTEXT)
|
||||
.toURL();
|
||||
System.out.println("Sending request to " + targetURL);
|
||||
final HttpURLConnection conn = (HttpURLConnection) targetURL.openConnection();
|
||||
try {
|
||||
conn.getResponseCode();
|
||||
Assert.fail("Request to " + targetURL + " was expected to fail during redirect");
|
||||
} catch (IOException ioe) {
|
||||
// expected because of the redirect to an invalid URL, for which a proxy can't be selected
|
||||
|
||||
// make sure the it was indeed a redirect
|
||||
Assert.assertTrue(handler.redirectSent, "Server was expected to send a redirect, but didn't");
|
||||
Assert.assertTrue(ourProxySelector.selectorUsedForRedirect, "Proxy selector wasn't used for redirect");
|
||||
|
||||
// make sure the IOException was caused by an IllegalArgumentException
|
||||
Assert.assertTrue(ioe.getCause() instanceof IllegalArgumentException, "Unexpected cause in the IOException");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static HttpServer createServer(final HttpHandler handler) throws IOException {
|
||||
final InetSocketAddress serverAddr = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
|
||||
final int backlog = -1;
|
||||
final HttpServer server = HttpServer.create(serverAddr, backlog);
|
||||
// setup the handler
|
||||
server.createContext(WEB_APP_CONTEXT, handler);
|
||||
// start the server
|
||||
server.start();
|
||||
System.out.println("Server started on " + server.getAddress());
|
||||
return server;
|
||||
}
|
||||
|
||||
private static class SimpleHandler implements HttpHandler {
|
||||
private volatile boolean redirectSent = false;
|
||||
|
||||
@Override
|
||||
public void handle(final HttpExchange httpExchange) throws IOException {
|
||||
final String redirectURL;
|
||||
try {
|
||||
redirectURL = new URI("http", "/irrelevant", null).toString();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
httpExchange.getResponseHeaders().add("Location", redirectURL);
|
||||
final URI requestURI = httpExchange.getRequestURI();
|
||||
System.out.println("Handling " + httpExchange.getRequestMethod() + " request "
|
||||
+ requestURI + " responding with redirect to " + redirectURL);
|
||||
this.redirectSent = true;
|
||||
httpExchange.sendResponseHeaders(301, -1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class CustomProxySelector extends DefaultProxySelector {
|
||||
|
||||
private volatile boolean selectorUsedForRedirect = false;
|
||||
|
||||
@Override
|
||||
public List<Proxy> select(final URI uri) {
|
||||
if (uri.toString().contains("/irrelevant")) {
|
||||
this.selectorUsedForRedirect = true;
|
||||
}
|
||||
return super.select(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test that Response Message gets set even if a non 100 response
|
||||
* gets return when Expect Continue is set
|
||||
* @bug 8352502
|
||||
* @library /test/lib
|
||||
* @run junit/othervm -Djdk.internal.httpclient.debug=true
|
||||
* -Djdk.httpclient.HttpClient.log=all
|
||||
* HttpUrlConnectionExpectContinueResponseMessageTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.Socket;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URL;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class HttpUrlConnectionExpectContinueResponseMessageTest {
|
||||
class Control {
|
||||
volatile ServerSocket serverSocket = null;
|
||||
volatile boolean stop = false;
|
||||
volatile String response = null;
|
||||
volatile Socket acceptingSocket = null;
|
||||
volatile String testPath = null;
|
||||
}
|
||||
|
||||
private Thread serverThread = null;
|
||||
private volatile Control control;
|
||||
static final Logger logger;
|
||||
|
||||
static {
|
||||
logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
|
||||
logger.setLevel(Level.ALL);
|
||||
Logger.getLogger("").getHandlers()[0].setLevel(Level.ALL);
|
||||
}
|
||||
|
||||
public Object[][] args() {
|
||||
return new Object[][]{
|
||||
// Expected Status Code, Status Line, Expected responseMessage
|
||||
{ 404, "HTTP/1.1 404 Not Found", "Not Found" },
|
||||
{ 405, "HTTP/1.1 405 Method Not Allowed", "Method Not Allowed" },
|
||||
{ 401, "HTTP/1.1 401 Unauthorized", "Unauthorized"}
|
||||
};
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public void startServerSocket() throws Exception {
|
||||
Control control = this.control = new Control();
|
||||
|
||||
control.serverSocket = new ServerSocket();
|
||||
control.serverSocket.setReuseAddress(true);
|
||||
control.serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
|
||||
Runnable runnable = () -> {
|
||||
while (!control.stop) {
|
||||
try {
|
||||
Socket socket = control.serverSocket.accept();
|
||||
String path = getPath(socket);
|
||||
|
||||
OutputStream outputStream;
|
||||
if (path.equals(control.testPath)) {
|
||||
control.acceptingSocket = socket;
|
||||
outputStream = control.acceptingSocket.getOutputStream();
|
||||
|
||||
// send a wrong response and then shutdown
|
||||
outputStream.write(control.response.getBytes());
|
||||
outputStream.flush();
|
||||
control.acceptingSocket.shutdownOutput();
|
||||
} else {
|
||||
// stray request showed up, return 500 and close socket
|
||||
outputStream = socket.getOutputStream();
|
||||
outputStream.write("HTTP/1.1 500 Internal Server Error\r\n".getBytes());
|
||||
outputStream.write("Connection: close\r\n".getBytes());
|
||||
outputStream.write("Content-Length: 0\r\n".getBytes());
|
||||
outputStream.write("\r\n".getBytes());
|
||||
outputStream.flush();
|
||||
socket.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Any exceptions will be ignored
|
||||
}
|
||||
}
|
||||
};
|
||||
serverThread = new Thread(runnable);
|
||||
serverThread.start();
|
||||
}
|
||||
|
||||
private static String getPath(Socket socket) throws IOException {
|
||||
InputStream inputStream = socket.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
|
||||
StringBuilder reqBuilder = new StringBuilder();
|
||||
String line = null;
|
||||
while (!(line = reader.readLine()).isEmpty()) {
|
||||
reqBuilder.append(line + "\r\n");
|
||||
}
|
||||
String req = reqBuilder.toString();
|
||||
StringTokenizer tokenizer = new StringTokenizer(req);
|
||||
String method = tokenizer.nextToken();
|
||||
String path = tokenizer.nextToken();
|
||||
return path;
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public void stopServerSocket() throws Exception {
|
||||
Control control = this.control;
|
||||
control.stop = true;
|
||||
control.serverSocket.close();
|
||||
serverThread.join();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("args")
|
||||
public void test(int expectedCode, String statusLine, String expectedMessage) throws Exception {
|
||||
String body = "Testing: " + expectedCode;
|
||||
Control control = this.control;
|
||||
control.response = statusLine + "\r\n"
|
||||
+ "Content-Length: 0\r\n"
|
||||
+ "\r\n";
|
||||
control.testPath = "/ContinueResponseMessageTest/" + expectedCode;
|
||||
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.port(control.serverSocket.getLocalPort())
|
||||
.path(control.testPath)
|
||||
.toURL();
|
||||
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Connection", "Close");
|
||||
connection.setRequestProperty("Expect", "100-Continue");
|
||||
|
||||
try {
|
||||
connection.setFixedLengthStreamingMode(body.getBytes().length);
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(body.getBytes());
|
||||
outputStream.close();
|
||||
} catch (Exception ex) {
|
||||
// server returning 4xx responses can result in exceptions
|
||||
// but we can just swallow them
|
||||
}
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
String responseMessage = connection.getResponseMessage();
|
||||
assertTrue(responseCode == expectedCode,
|
||||
String.format("Expected %s response, instead received %s", expectedCode, responseCode));
|
||||
assertTrue(expectedMessage.equals(responseMessage),
|
||||
String.format("Expected Response Message %s, instead received %s",
|
||||
expectedMessage, responseMessage));
|
||||
control.acceptingSocket.close();
|
||||
}
|
||||
}
|
||||
72
test/jdk/java/net/HttpURLConnection/NoProxyTest.java
Normal file
72
test/jdk/java/net/HttpURLConnection/NoProxyTest.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8144008
|
||||
* @library /test/lib
|
||||
* @summary Setting NO_PROXY on HTTP URL connections does not stop proxying
|
||||
* @run main/othervm NoProxyTest
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.List;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class NoProxyTest {
|
||||
|
||||
static class NoProxyTestSelector extends ProxySelector {
|
||||
@Override
|
||||
public List<Proxy> select(URI uri) {
|
||||
throw new RuntimeException("Should not reach here as proxy==Proxy.NO_PROXY");
|
||||
}
|
||||
@Override
|
||||
public void connectFailed(URI u, SocketAddress s, IOException e) { }
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws MalformedURLException {
|
||||
ProxySelector.setDefault(new NoProxyTestSelector());
|
||||
|
||||
URL url = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.loopback()
|
||||
.path("/")
|
||||
.toURLUnchecked();
|
||||
System.out.println("URL: " + url);
|
||||
URLConnection connection;
|
||||
try {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
connection.connect();
|
||||
} catch (IOException ignore) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
228
test/jdk/java/net/HttpURLConnection/Response1xxTest.java
Normal file
228
test/jdk/java/net/HttpURLConnection/Response1xxTest.java
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8170305
|
||||
* @summary Tests behaviour of HttpURLConnection when server responds with 1xx interim response status codes
|
||||
* @library /test/lib
|
||||
* @run testng Response1xxTest
|
||||
*/
|
||||
public class Response1xxTest {
|
||||
private static final String EXPECTED_RSP_BODY = "Hello World";
|
||||
|
||||
private ServerSocket serverSocket;
|
||||
private Http11Server server;
|
||||
private String requestURIBase;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
serverSocket = new ServerSocket(0, 0, InetAddress.getLoopbackAddress());
|
||||
server = new Http11Server(serverSocket);
|
||||
new Thread(server).start();
|
||||
requestURIBase = URIBuilder.newBuilder().scheme("http").loopback()
|
||||
.port(serverSocket.getLocalPort()).build().toString();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public void teardown() throws Exception {
|
||||
if (server != null) {
|
||||
server.stop = true;
|
||||
System.out.println("(HTTP 1.1) Server stop requested");
|
||||
}
|
||||
if (serverSocket != null) {
|
||||
serverSocket.close();
|
||||
System.out.println("Closed (HTTP 1.1) server socket");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Http11Server implements Runnable {
|
||||
private static final int CONTENT_LENGTH = EXPECTED_RSP_BODY.getBytes(StandardCharsets.UTF_8).length;
|
||||
|
||||
private static final String HTTP_1_1_RSP_200 = "HTTP/1.1 200 OK\r\n" +
|
||||
"Content-Length: " + CONTENT_LENGTH + "\r\n\r\n" +
|
||||
EXPECTED_RSP_BODY;
|
||||
|
||||
private static final String REQ_LINE_FOO = "GET /test/foo HTTP/1.1\r\n";
|
||||
private static final String REQ_LINE_BAR = "GET /test/bar HTTP/1.1\r\n";
|
||||
private static final String REQ_LINE_HELLO = "GET /test/hello HTTP/1.1\r\n";
|
||||
private static final String REQ_LINE_BYE = "GET /test/bye HTTP/1.1\r\n";
|
||||
|
||||
|
||||
private final ServerSocket serverSocket;
|
||||
private volatile boolean stop;
|
||||
|
||||
private Http11Server(final ServerSocket serverSocket) {
|
||||
this.serverSocket = serverSocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Server running at " + serverSocket);
|
||||
while (!stop) {
|
||||
Socket socket = null;
|
||||
try {
|
||||
// accept a connection
|
||||
socket = serverSocket.accept();
|
||||
System.out.println("Accepted connection from client " + socket);
|
||||
// read request
|
||||
final String requestLine;
|
||||
try {
|
||||
requestLine = readRequestLine(socket);
|
||||
} catch (Throwable t) {
|
||||
// ignore connections from potential rogue client
|
||||
System.err.println("Ignoring connection/request from client " + socket
|
||||
+ " due to exception:");
|
||||
t.printStackTrace();
|
||||
// close the socket
|
||||
safeClose(socket);
|
||||
continue;
|
||||
}
|
||||
System.out.println("Received following request line from client " + socket
|
||||
+ " :\n" + requestLine);
|
||||
final int informationalResponseCode;
|
||||
if (requestLine.startsWith(REQ_LINE_FOO)) {
|
||||
// we will send intermediate/informational 102 response
|
||||
informationalResponseCode = 102;
|
||||
} else if (requestLine.startsWith(REQ_LINE_BAR)) {
|
||||
// we will send intermediate/informational 103 response
|
||||
informationalResponseCode = 103;
|
||||
} else if (requestLine.startsWith(REQ_LINE_HELLO)) {
|
||||
// we will send intermediate/informational 100 response
|
||||
informationalResponseCode = 100;
|
||||
} else if (requestLine.startsWith(REQ_LINE_BYE)) {
|
||||
// we will send intermediate/informational 101 response
|
||||
informationalResponseCode = 101;
|
||||
} else {
|
||||
// unexpected client. ignore and close the client
|
||||
System.err.println("Ignoring unexpected request from client " + socket);
|
||||
safeClose(socket);
|
||||
continue;
|
||||
}
|
||||
try (final OutputStream os = socket.getOutputStream()) {
|
||||
// send informational response headers a few times (spec allows them to
|
||||
// be sent multiple times)
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// send 1xx response header
|
||||
os.write(("HTTP/1.1 " + informationalResponseCode + "\r\n\r\n")
|
||||
.getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
System.out.println("Sent response code " + informationalResponseCode
|
||||
+ " to client " + socket);
|
||||
}
|
||||
// now send a final response
|
||||
System.out.println("Now sending 200 response code to client " + socket);
|
||||
os.write(HTTP_1_1_RSP_200.getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
System.out.println("Sent 200 response code to client " + socket);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// close the client connection
|
||||
safeClose(socket);
|
||||
// continue accepting any other client connections until we are asked to stop
|
||||
System.err.println("Ignoring exception in server:");
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String readRequestLine(final Socket sock) throws IOException {
|
||||
final InputStream is = sock.getInputStream();
|
||||
final StringBuilder sb = new StringBuilder("");
|
||||
byte[] buf = new byte[1024];
|
||||
while (!sb.toString().endsWith("\r\n\r\n")) {
|
||||
final int numRead = is.read(buf);
|
||||
if (numRead == -1) {
|
||||
return sb.toString();
|
||||
}
|
||||
final String part = new String(buf, 0, numRead, StandardCharsets.ISO_8859_1);
|
||||
sb.append(part);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void safeClose(final Socket socket) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (Throwable t) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when a HTTP/1.1 server sends intermediate 1xx response codes and then the final
|
||||
* response, the client (internally) will ignore those intermediate informational response codes
|
||||
* and only return the final response to the application
|
||||
*/
|
||||
@Test
|
||||
public void test1xx() throws Exception {
|
||||
final URI[] requestURIs = new URI[]{
|
||||
new URI(requestURIBase + "/test/foo"),
|
||||
new URI(requestURIBase + "/test/bar"),
|
||||
new URI(requestURIBase + "/test/hello")};
|
||||
for (final URI requestURI : requestURIs) {
|
||||
System.out.println("Issuing request to " + requestURI);
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) requestURI.toURL().openConnection();
|
||||
final int responseCode = urlConnection.getResponseCode();
|
||||
Assert.assertEquals(responseCode, 200, "Unexpected response code");
|
||||
final String body;
|
||||
try (final InputStream is = urlConnection.getInputStream()) {
|
||||
final byte[] bytes = is.readAllBytes();
|
||||
body = new String(bytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
Assert.assertEquals(body, EXPECTED_RSP_BODY, "Unexpected response body");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when a HTTP/1.1 server sends 101 response code, when the client
|
||||
* didn't ask for a connection upgrade, then the request fails with an exception.
|
||||
*/
|
||||
@Test
|
||||
public void test101CausesRequestFailure() throws Exception {
|
||||
final URI requestURI = new URI(requestURIBase + "/test/bye");
|
||||
System.out.println("Issuing request to " + requestURI);
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) requestURI.toURL().openConnection();
|
||||
// we expect the request to fail because the server unexpectedly sends a 101 response
|
||||
Assert.assertThrows(ProtocolException.class, () -> urlConnection.getResponseCode());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2023, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Authenticator;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8169415
|
||||
* @library /test/lib
|
||||
* @modules java.logging
|
||||
* java.base/sun.net.www
|
||||
* java.base/sun.net.www.protocol.http
|
||||
* jdk.httpserver/sun.net.httpserver
|
||||
* @build jdk.test.lib.net.SimpleSSLContext HTTPTest HTTPTestServer HTTPTestClient HTTPSetAuthenticatorTest
|
||||
* @summary A simple HTTP test that starts an echo server supporting the given
|
||||
* authentication scheme, then starts a regular HTTP client to invoke it.
|
||||
* The client first does a GET request on "/", then follows on
|
||||
* with a POST request that sends "Hello World!" to the server.
|
||||
* The client expects to receive "Hello World!" in return.
|
||||
* The test supports several execution modes:
|
||||
* SERVER: The server performs Server authentication;
|
||||
* PROXY: The server pretends to be a proxy and performs
|
||||
* Proxy authentication;
|
||||
* SERVER307: The server redirects the client (307) to another
|
||||
* server that perform Server authentication;
|
||||
* PROXY305: The server attempts to redirect
|
||||
* the client to a proxy using 305 code;
|
||||
* This test runs the client several times, providing different
|
||||
* authenticators to the HttpURLConnection and verifies that
|
||||
* the authenticator is invoked as expected - validating that
|
||||
* connections with different authenticators do not share each
|
||||
* other's socket channel and authentication info.
|
||||
* Note: BASICSERVER means that the server will let the underlying
|
||||
* com.sun.net.httpserver.HttpServer perform BASIC
|
||||
* authentication when in Server mode. There should be
|
||||
* no real difference between BASICSERVER and BASIC - it should
|
||||
* be transparent on the client side.
|
||||
* @run main/othervm HTTPSetAuthenticatorTest NONE SERVER PROXY SERVER307 PROXY305
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5 HTTPSetAuthenticatorTest DIGEST SERVER
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5 HTTPSetAuthenticatorTest DIGEST PROXY
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5 HTTPSetAuthenticatorTest DIGEST PROXY305
|
||||
* @run main/othervm -Dhttp.auth.digest.reEnabledAlgorithms=MD5 HTTPSetAuthenticatorTest DIGEST SERVER307
|
||||
* @run main/othervm HTTPSetAuthenticatorTest BASIC SERVER
|
||||
* @run main/othervm HTTPSetAuthenticatorTest BASIC PROXY
|
||||
* @run main/othervm HTTPSetAuthenticatorTest BASIC PROXY305
|
||||
* @run main/othervm HTTPSetAuthenticatorTest BASIC SERVER307
|
||||
* @run main/othervm HTTPSetAuthenticatorTest BASICSERVER SERVER
|
||||
* @run main/othervm HTTPSetAuthenticatorTest BASICSERVER SERVER307
|
||||
*
|
||||
* @author danielfuchs
|
||||
*/
|
||||
public class HTTPSetAuthenticatorTest extends HTTPTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String[] schemes;
|
||||
String[] params;
|
||||
if (args == null || args.length == 0) {
|
||||
schemes = Stream.of(HttpSchemeType.values())
|
||||
.map(HttpSchemeType::name)
|
||||
.collect(Collectors.toList())
|
||||
.toArray(new String[0]);
|
||||
params = new String[0];
|
||||
} else {
|
||||
schemes = new String[] { args[0] };
|
||||
params = Arrays.copyOfRange(args, 1, args.length);
|
||||
}
|
||||
for (String scheme : schemes) {
|
||||
System.out.println("==== Testing with scheme=" + scheme + " ====\n");
|
||||
new HTTPSetAuthenticatorTest(HttpSchemeType.valueOf(scheme))
|
||||
.execute(params);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
final HttpSchemeType scheme;
|
||||
public HTTPSetAuthenticatorTest(HttpSchemeType scheme) {
|
||||
this.scheme = scheme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSchemeType getHttpSchemeType() {
|
||||
return scheme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int run(HTTPTestServer server,
|
||||
HttpProtocolType protocol,
|
||||
HttpAuthType mode)
|
||||
throws IOException
|
||||
{
|
||||
HttpTestAuthenticator authOne = new HttpTestAuthenticator("authOne", "dublin", "foox");
|
||||
HttpTestAuthenticator authTwo = new HttpTestAuthenticator("authTwo", "dublin", "foox");
|
||||
int expectedIncrement = scheme == HttpSchemeType.NONE
|
||||
? 0 : EXPECTED_AUTH_CALLS_PER_TEST;
|
||||
int count;
|
||||
int defaultCount = AUTHENTICATOR.count.get();
|
||||
// Connect to the server with a GET request, then with a
|
||||
// POST that contains "Hello World!"
|
||||
// Uses authenticator #1
|
||||
System.out.println("\nClient: Using authenticator #1: "
|
||||
+ toString(authOne));
|
||||
HTTPTestClient.connect(protocol, server, mode, authOne);
|
||||
count = authOne.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #1 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
|
||||
// Connect to the server with a GET request, then with a
|
||||
// POST that contains "Hello World!"
|
||||
// Uses authenticator #2
|
||||
System.out.println("\nClient: Using authenticator #2: "
|
||||
+ toString(authTwo));
|
||||
HTTPTestClient.connect(protocol, server, mode, authTwo);
|
||||
count = authTwo.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #2 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
|
||||
// Connect to the server with a GET request, then with a
|
||||
// POST that contains "Hello World!"
|
||||
// Uses authenticator #1
|
||||
System.out.println("\nClient: Using authenticator #1 again: "
|
||||
+ toString(authOne));
|
||||
HTTPTestClient.connect(protocol, server, mode, authOne);
|
||||
count = authOne.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #1 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
count = authTwo.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #2 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
count = AUTHENTICATOR.count.get();
|
||||
if (count != defaultCount) {
|
||||
throw new AssertionError("Default Authenticator called " + count(count)
|
||||
+ " expected it to be called " + expected(defaultCount));
|
||||
}
|
||||
|
||||
// Now tries with the default authenticator: it should be invoked.
|
||||
System.out.println("\nClient: Using the default authenticator: "
|
||||
+ toString(null));
|
||||
HTTPTestClient.connect(protocol, server, mode, null);
|
||||
count = authOne.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #1 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
count = authTwo.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #2 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
count = AUTHENTICATOR.count.get();
|
||||
if (count != defaultCount + expectedIncrement) {
|
||||
throw new AssertionError("Default Authenticator called " + count(count)
|
||||
+ " expected it to be called " + expected(defaultCount + expectedIncrement));
|
||||
}
|
||||
|
||||
// Now tries with explicitly setting the default authenticator: it should
|
||||
// be invoked again.
|
||||
// Uncomment the code below when 8169068 is available.
|
||||
System.out.println("\nClient: Explicitly setting the default authenticator: "
|
||||
+ toString(Authenticator.getDefault()));
|
||||
HTTPTestClient.connect(protocol, server, mode, Authenticator.getDefault());
|
||||
count = authOne.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #1 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
count = authTwo.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #2 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
count = AUTHENTICATOR.count.get();
|
||||
if (count != defaultCount + 2 * expectedIncrement) {
|
||||
throw new AssertionError("Default Authenticator called " + count(count)
|
||||
+ " expected it to be called "
|
||||
+ expected(defaultCount + 2 * expectedIncrement));
|
||||
}
|
||||
|
||||
// Now tries to set an authenticator on a connected connection.
|
||||
URL url = url(protocol, server.getAddress(), "/");
|
||||
Proxy proxy = proxy(server, mode);
|
||||
HttpURLConnection conn = openConnection(url, mode, proxy);
|
||||
try {
|
||||
conn.setAuthenticator(null);
|
||||
throw new RuntimeException("Expected NullPointerException"
|
||||
+ " trying to set a null authenticator"
|
||||
+ " not raised.");
|
||||
} catch (NullPointerException npe) {
|
||||
System.out.println("Client: caught expected NPE"
|
||||
+ " trying to set a null authenticator: "
|
||||
+ npe);
|
||||
}
|
||||
conn.connect();
|
||||
try {
|
||||
try {
|
||||
conn.setAuthenticator(authOne);
|
||||
throw new RuntimeException("Expected IllegalStateException"
|
||||
+ " trying to set an authenticator after connect"
|
||||
+ " not raised.");
|
||||
} catch (IllegalStateException ise) {
|
||||
System.out.println("Client: caught expected ISE"
|
||||
+ " trying to set an authenticator after connect: "
|
||||
+ ise);
|
||||
}
|
||||
// Uncomment the code below when 8169068 is available.
|
||||
try {
|
||||
conn.setAuthenticator(Authenticator.getDefault());
|
||||
throw new RuntimeException("Expected IllegalStateException"
|
||||
+ " trying to set an authenticator after connect"
|
||||
+ " not raised.");
|
||||
} catch (IllegalStateException ise) {
|
||||
System.out.println("Client: caught expected ISE"
|
||||
+ " trying to set an authenticator after connect: "
|
||||
+ ise);
|
||||
}
|
||||
try {
|
||||
conn.setAuthenticator(null);
|
||||
throw new RuntimeException("Expected"
|
||||
+ " IllegalStateException or NullPointerException"
|
||||
+ " trying to set a null authenticator after connect"
|
||||
+ " not raised.");
|
||||
} catch (IllegalStateException | NullPointerException xxe) {
|
||||
System.out.println("Client: caught expected "
|
||||
+ xxe.getClass().getSimpleName()
|
||||
+ " trying to set a null authenticator after connect: "
|
||||
+ xxe);
|
||||
}
|
||||
} finally {
|
||||
conn.disconnect();
|
||||
}
|
||||
|
||||
// double check that authOne and authTwo haven't been invoked.
|
||||
count = authOne.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #1 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
count = authTwo.count.get();
|
||||
if (count != expectedIncrement) {
|
||||
throw new AssertionError("Authenticator #2 called " + count(count)
|
||||
+ " expected it to be called " + expected(expectedIncrement));
|
||||
}
|
||||
|
||||
// All good!
|
||||
// return the number of times the default authenticator is supposed
|
||||
// to have been called.
|
||||
return scheme == HttpSchemeType.NONE ? 0 : 2 * EXPECTED_AUTH_CALLS_PER_TEST;
|
||||
}
|
||||
|
||||
static String toString(Authenticator a) {
|
||||
return a == null ? "null" : a.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2026, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.Authenticator;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import jdk.test.lib.net.SimpleSSLContext;
|
||||
import static java.net.Proxy.NO_PROXY;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8169415
|
||||
* @library /test/lib
|
||||
* @modules java.logging
|
||||
* java.base/sun.net.www
|
||||
* jdk.httpserver/sun.net.httpserver
|
||||
* @build jdk.test.lib.net.SimpleSSLContext HTTPTest HTTPTestServer HTTPTestClient
|
||||
* @summary A simple HTTP test that starts an echo server supporting Digest
|
||||
* authentication, then starts a regular HTTP client to invoke it.
|
||||
* The client first does a GET request on "/", then follows on
|
||||
* with a POST request that sends "Hello World!" to the server.
|
||||
* The client expects to receive "Hello World!" in return.
|
||||
* The test supports several execution modes:
|
||||
* SERVER: The server performs Digest Server authentication;
|
||||
* PROXY: The server pretends to be a proxy and performs
|
||||
* Digest Proxy authentication;
|
||||
* SERVER307: The server redirects the client (307) to another
|
||||
* server that perform Digest authentication;
|
||||
* PROXY305: The server attempts to redirect
|
||||
* the client to a proxy using 305 code;
|
||||
* @run main/othervm -Dtest.debug=true -Dtest.digest.algorithm=SHA-512 HTTPTest SERVER
|
||||
* @run main/othervm -Dtest.debug=true -Dtest.digest.algorithm=SHA-256 HTTPTest SERVER
|
||||
* @run main/othervm -Dtest.debug=true -Dhttp.auth.digest.reEnabledAlgorithms=MD5 HTTPTest SERVER
|
||||
* @run main/othervm -Dtest.debug=true -Dhttp.auth.digest.reEnabledAlgorithms=MD5 HTTPTest PROXY
|
||||
* @run main/othervm -Dtest.debug=true -Dhttp.auth.digest.reEnabledAlgorithms=MD5 HTTPTest SERVER307
|
||||
* @run main/othervm -Dtest.debug=true -Dhttp.auth.digest.reEnabledAlgorithms=MD5 HTTPTest PROXY305
|
||||
*
|
||||
* @author danielfuchs
|
||||
*/
|
||||
public class HTTPTest {
|
||||
public static final boolean DEBUG =
|
||||
Boolean.parseBoolean(System.getProperty("test.debug", "false"));
|
||||
public static enum HttpAuthType { SERVER, PROXY, SERVER307, PROXY305 };
|
||||
public static enum HttpProtocolType { HTTP, HTTPS };
|
||||
public static enum HttpSchemeType { NONE, BASICSERVER, BASIC, DIGEST };
|
||||
public static final HttpAuthType DEFAULT_HTTP_AUTH_TYPE = HttpAuthType.SERVER;
|
||||
public static final HttpProtocolType DEFAULT_PROTOCOL_TYPE = HttpProtocolType.HTTP;
|
||||
public static final HttpSchemeType DEFAULT_SCHEME_TYPE = HttpSchemeType.DIGEST;
|
||||
|
||||
public static class HttpTestAuthenticator extends Authenticator {
|
||||
private final String realm;
|
||||
private final String username;
|
||||
// Used to prevent incrementation of 'count' when calling the
|
||||
// authenticator from the server side.
|
||||
private final ThreadLocal<Boolean> skipCount = new ThreadLocal<>();
|
||||
// count will be incremented every time getPasswordAuthentication()
|
||||
// is called from the client side.
|
||||
final AtomicInteger count = new AtomicInteger();
|
||||
private final String name;
|
||||
|
||||
public HttpTestAuthenticator(String name, String realm, String username) {
|
||||
this.name = name;
|
||||
this.realm = realm;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
if (skipCount.get() == null || skipCount.get().booleanValue() == false) {
|
||||
System.out.println("Authenticator " + name + " called: " + count.incrementAndGet());
|
||||
}
|
||||
return new PasswordAuthentication(getUserName(),
|
||||
new char[] {'b','a','r'});
|
||||
}
|
||||
|
||||
// Called by the server side to get the password of the user
|
||||
// being authentified.
|
||||
public final char[] getPassword(String user) {
|
||||
if (user.equals(username)) {
|
||||
skipCount.set(Boolean.TRUE);
|
||||
try {
|
||||
return getPasswordAuthentication().getPassword();
|
||||
} finally {
|
||||
skipCount.set(Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
throw new SecurityException("User unknown: " + user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "[name=\"" + name + "\"]";
|
||||
}
|
||||
|
||||
public final String getUserName() {
|
||||
return username;
|
||||
}
|
||||
public final String getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
}
|
||||
public static final HttpTestAuthenticator AUTHENTICATOR;
|
||||
static {
|
||||
AUTHENTICATOR = new HttpTestAuthenticator("AUTHENTICATOR","dublin", "foox");
|
||||
Authenticator.setDefault(AUTHENTICATOR);
|
||||
}
|
||||
|
||||
static {
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
SSLContext.setDefault(SimpleSSLContext.findSSLContext());
|
||||
}
|
||||
|
||||
static final Logger logger = Logger.getLogger ("com.sun.net.httpserver");
|
||||
static {
|
||||
if (DEBUG) logger.setLevel(Level.ALL);
|
||||
Stream.of(Logger.getLogger("").getHandlers())
|
||||
.forEach(h -> h.setLevel(Level.ALL));
|
||||
}
|
||||
|
||||
static final int EXPECTED_AUTH_CALLS_PER_TEST = 1;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// new HTTPTest().execute(HttpAuthType.SERVER.name());
|
||||
new HTTPTest().execute(args);
|
||||
}
|
||||
|
||||
public void execute(String... args) throws Exception {
|
||||
Stream<HttpAuthType> modes;
|
||||
if (args == null || args.length == 0) {
|
||||
modes = Stream.of(HttpAuthType.values());
|
||||
} else {
|
||||
modes = Stream.of(args).map(HttpAuthType::valueOf);
|
||||
}
|
||||
modes.forEach(this::test);
|
||||
System.out.println("Test PASSED - Authenticator called: "
|
||||
+ expected(AUTHENTICATOR.count.get()));
|
||||
}
|
||||
|
||||
public void test(HttpAuthType mode) {
|
||||
for (HttpProtocolType type: HttpProtocolType.values()) {
|
||||
test(type, mode);
|
||||
}
|
||||
}
|
||||
|
||||
public HttpSchemeType getHttpSchemeType() {
|
||||
return DEFAULT_SCHEME_TYPE;
|
||||
}
|
||||
|
||||
public void test(HttpProtocolType protocol, HttpAuthType mode) {
|
||||
if (mode == HttpAuthType.PROXY305 && protocol == HttpProtocolType.HTTPS ) {
|
||||
// silently skip unsupported test combination
|
||||
return;
|
||||
}
|
||||
String digestalg = System.getProperty("test.digest.algorithm");
|
||||
if (digestalg == null || "".equals(digestalg))
|
||||
digestalg = "MD5";
|
||||
|
||||
System.out.println("\n**** Testing " + protocol + " "
|
||||
+ mode + " mode ****\n");
|
||||
int authCount = AUTHENTICATOR.count.get();
|
||||
int expectedIncrement = 0;
|
||||
try {
|
||||
// Creates an HTTP server that echoes back whatever is in the
|
||||
// request body.
|
||||
HTTPTestServer server =
|
||||
HTTPTestServer.create(protocol,
|
||||
mode,
|
||||
AUTHENTICATOR,
|
||||
getHttpSchemeType(),
|
||||
null,
|
||||
digestalg);
|
||||
try {
|
||||
expectedIncrement += run(server, protocol, mode);
|
||||
} finally {
|
||||
server.stop();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace(System.err);
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
int count = AUTHENTICATOR.count.get();
|
||||
if (count != authCount + expectedIncrement) {
|
||||
throw new AssertionError("Authenticator called " + count(count)
|
||||
+ " expected it to be called "
|
||||
+ expected(authCount + expectedIncrement));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the test with the given parameters.
|
||||
* @param server The server
|
||||
* @param protocol The protocol (HTTP/HTTPS)
|
||||
* @param mode The mode (PROXY, SERVER, SERVER307...)
|
||||
* @return The number of times the default authenticator should have been
|
||||
* called.
|
||||
* @throws IOException in case of connection or protocol issues
|
||||
*/
|
||||
public int run(HTTPTestServer server,
|
||||
HttpProtocolType protocol,
|
||||
HttpAuthType mode)
|
||||
throws IOException
|
||||
{
|
||||
// Connect to the server with a GET request, then with a
|
||||
// POST that contains "Hello World!"
|
||||
HTTPTestClient.connect(protocol, server, mode, null);
|
||||
// return the number of times the default authenticator is supposed
|
||||
// to have been called.
|
||||
return EXPECTED_AUTH_CALLS_PER_TEST;
|
||||
}
|
||||
|
||||
public static String count(int count) {
|
||||
switch(count) {
|
||||
case 0: return "not even once";
|
||||
case 1: return "once";
|
||||
case 2: return "twice";
|
||||
default: return String.valueOf(count) + " times";
|
||||
}
|
||||
}
|
||||
|
||||
public static String expected(int count) {
|
||||
switch(count) {
|
||||
default: return count(count);
|
||||
}
|
||||
}
|
||||
public static String protocol(HttpProtocolType type) {
|
||||
return type.name().toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
public static URL url(HttpProtocolType protocol, InetSocketAddress address,
|
||||
String path) throws MalformedURLException {
|
||||
return new URL(protocol(protocol),
|
||||
address.getAddress().getHostAddress(),
|
||||
address.getPort(), path);
|
||||
}
|
||||
|
||||
public static Proxy proxy(HTTPTestServer server, HttpAuthType authType) {
|
||||
if (authType != HttpAuthType.PROXY) return null;
|
||||
|
||||
InetSocketAddress proxyAddress = server.getProxyAddress();
|
||||
if (!proxyAddress.isUnresolved()) {
|
||||
// Forces the proxy to use an unresolved address created
|
||||
// from the actual IP address to avoid using the proxy
|
||||
// address hostname which would result in resolving to
|
||||
// a posibly different address. For instance we want to
|
||||
// avoid cases such as:
|
||||
// ::1 => "localhost" => 127.0.0.1
|
||||
proxyAddress = InetSocketAddress.
|
||||
createUnresolved(proxyAddress.getAddress().getHostAddress(),
|
||||
proxyAddress.getPort());
|
||||
}
|
||||
|
||||
return new Proxy(Proxy.Type.HTTP, proxyAddress);
|
||||
}
|
||||
|
||||
public static HttpURLConnection openConnection(URL url,
|
||||
HttpAuthType authType,
|
||||
Proxy proxy)
|
||||
throws IOException {
|
||||
|
||||
HttpURLConnection conn = (HttpURLConnection)
|
||||
(authType == HttpAuthType.PROXY
|
||||
? url.openConnection(proxy)
|
||||
: url.openConnection(NO_PROXY));
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2026, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Authenticator;
|
||||
import java.net.BindException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
/**
|
||||
* A simple Http client that connects to the HTTPTestServer.
|
||||
* @author danielfuchs
|
||||
*/
|
||||
public class HTTPTestClient extends HTTPTest {
|
||||
|
||||
public static final long DELAY_BEFORE_RETRY = 2500; // milliseconds
|
||||
|
||||
public static void connect(HttpProtocolType protocol,
|
||||
HTTPTestServer server,
|
||||
HttpAuthType authType,
|
||||
Authenticator auth)
|
||||
throws IOException {
|
||||
try {
|
||||
doConnect(protocol, server, authType, auth);
|
||||
} catch (BindException ex) {
|
||||
// sleep a bit then try again once
|
||||
System.out.println("WARNING: Unexpected BindException: " + ex);
|
||||
System.out.println("\tSleeping a bit and try again...");
|
||||
long start = System.nanoTime();
|
||||
System.gc();
|
||||
try {
|
||||
Thread.sleep(DELAY_BEFORE_RETRY);
|
||||
} catch (InterruptedException iex) {
|
||||
// ignore
|
||||
}
|
||||
System.gc();
|
||||
System.out.println("\tRetrying after "
|
||||
+ Duration.ofNanos(System.nanoTime() - start).toMillis()
|
||||
+ " milliseconds");
|
||||
doConnect(protocol, server, authType, auth);
|
||||
}
|
||||
}
|
||||
|
||||
public static void doConnect(HttpProtocolType protocol,
|
||||
HTTPTestServer server,
|
||||
HttpAuthType authType,
|
||||
Authenticator auth)
|
||||
throws IOException {
|
||||
|
||||
InetSocketAddress address = server.getAddress();
|
||||
final URL url = url(protocol, address, "/");
|
||||
final Proxy proxy = proxy(server, authType);
|
||||
|
||||
System.out.println("Client: FIRST request: " + url + " GET");
|
||||
HttpURLConnection conn = openConnection(url, authType, proxy);
|
||||
configure(conn, auth);
|
||||
System.out.println("Response code: " + conn.getResponseCode());
|
||||
String result = new String(conn.getInputStream().readAllBytes(), "UTF-8");
|
||||
System.out.println("Response body: " + result);
|
||||
if (!result.isEmpty()) {
|
||||
throw new RuntimeException("Unexpected response to GET: " + result);
|
||||
}
|
||||
System.out.println("\nClient: NEXT request: " + url + " POST");
|
||||
conn = openConnection(url, authType, proxy);
|
||||
configure(conn, auth);
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
conn.getOutputStream().write("Hello World!".getBytes("UTF-8"));
|
||||
System.out.println("Response code: " + conn.getResponseCode());
|
||||
result = new String(conn.getInputStream().readAllBytes(), "UTF-8");
|
||||
System.out.println("Response body: " + result);
|
||||
if ("Hello World!".equals(result)) {
|
||||
System.out.println("Test passed!");
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected response to POST: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
private static void configure(HttpURLConnection conn, Authenticator auth)
|
||||
throws IOException {
|
||||
if (auth != null) {
|
||||
conn.setAuthenticator(auth);
|
||||
}
|
||||
if (conn instanceof HttpsURLConnection) {
|
||||
System.out.println("Client: configuring SSL connection");
|
||||
// We have set a default SSLContext so we don't need to do
|
||||
// anything here. Otherwise it could look like:
|
||||
// HttpsURLConnection httpsConn = (HttpsURLConnection)conn;
|
||||
// httpsConn.setSSLSocketFactory(
|
||||
// SimpleSSLContext.findSSLContext().getSocketFactory());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
157
test/jdk/java/net/HttpURLConnection/UnmodifiableMaps.java
Normal file
157
test/jdk/java/net/HttpURLConnection/UnmodifiableMaps.java
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 7128648
|
||||
* @library /test/lib
|
||||
* @modules jdk.httpserver
|
||||
* @summary HttpURLConnection.getHeaderFields should return an unmodifiable Map
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import com.sun.net.httpserver.Headers;
|
||||
import static java.net.Proxy.NO_PROXY;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
public class UnmodifiableMaps {
|
||||
|
||||
void test(String[] args) throws Exception {
|
||||
HttpServer server = startHttpServer();
|
||||
try {
|
||||
InetSocketAddress address = server.getAddress();
|
||||
URI uri = URIBuilder.newBuilder()
|
||||
.scheme("http")
|
||||
.host(address.getAddress())
|
||||
.port(address.getPort())
|
||||
.path("/foo")
|
||||
.build();
|
||||
doClient(uri);
|
||||
} finally {
|
||||
server.stop(0);
|
||||
}
|
||||
}
|
||||
|
||||
void doClient(URI uri) throws Exception {
|
||||
HttpURLConnection uc = (HttpURLConnection) uri.toURL().openConnection(NO_PROXY);
|
||||
|
||||
// Test1: getRequestProperties is unmodifiable
|
||||
System.out.println("Check getRequestProperties");
|
||||
checkUnmodifiable(uc.getRequestProperties());
|
||||
uc.addRequestProperty("X", "V");
|
||||
uc.addRequestProperty("X1", "V1");
|
||||
checkUnmodifiable(uc.getRequestProperties());
|
||||
|
||||
int resp = uc.getResponseCode();
|
||||
check(resp == 200,
|
||||
"Unexpected response code. Expected 200, got " + resp);
|
||||
|
||||
// Test2: getHeaderFields is unmodifiable
|
||||
System.out.println("Check getHeaderFields");
|
||||
checkUnmodifiable(uc.getHeaderFields());
|
||||
// If the implementation does caching, check again.
|
||||
checkUnmodifiable(uc.getHeaderFields());
|
||||
}
|
||||
|
||||
// HTTP Server
|
||||
HttpServer startHttpServer() throws IOException {
|
||||
InetAddress loopback = InetAddress.getLoopbackAddress();
|
||||
HttpServer httpServer = HttpServer.create(new InetSocketAddress(loopback, 0), 0);
|
||||
httpServer.createContext("/foo", new SimpleHandler());
|
||||
httpServer.start();
|
||||
return httpServer;
|
||||
}
|
||||
|
||||
class SimpleHandler implements HttpHandler {
|
||||
@Override
|
||||
public void handle(HttpExchange t) throws IOException {
|
||||
Headers respHeaders = t.getResponseHeaders();
|
||||
// ensure some response headers, over the usual ones
|
||||
respHeaders.add("RespHdr1", "Value1");
|
||||
respHeaders.add("RespHdr2", "Value2");
|
||||
respHeaders.add("RespHdr3", "Value3");
|
||||
t.sendResponseHeaders(200, -1);
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
|
||||
void checkUnmodifiable(Map<String,List<String>> map) {
|
||||
checkUnmodifiableMap(map);
|
||||
|
||||
// Now check the individual values
|
||||
Collection<List<String>> values = map.values();
|
||||
for (List<String> value : values) {
|
||||
checkUnmodifiableList(value);
|
||||
}
|
||||
}
|
||||
|
||||
void checkUnmodifiableMap(final Map<String,List<String>> map) {
|
||||
expectThrow( new Runnable() {
|
||||
public void run() { map.clear(); }});
|
||||
expectThrow( new Runnable() {
|
||||
public void run() { map.put("X", new ArrayList<String>()); }});
|
||||
expectThrow( new Runnable() {
|
||||
public void run() { map.remove("X"); }});
|
||||
}
|
||||
|
||||
void checkUnmodifiableList(final List<String> list) {
|
||||
expectThrow( new Runnable() {
|
||||
public void run() { list.clear(); }});
|
||||
expectThrow( new Runnable() {
|
||||
public void run() { list.add("X"); }});
|
||||
expectThrow( new Runnable() {
|
||||
public void run() { list.remove("X"); }});
|
||||
}
|
||||
|
||||
void expectThrow(Runnable r) {
|
||||
try { r.run(); fail("Excepted UOE to be thrown."); Thread.dumpStack(); }
|
||||
catch (UnsupportedOperationException e) { pass(); }
|
||||
}
|
||||
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++;}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
||||
64
test/jdk/java/net/HttpURLConnection/getResponseCode.java
Normal file
64
test/jdk/java/net/HttpURLConnection/getResponseCode.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4666195
|
||||
* @build getResponseCode
|
||||
* @run main getResponseCode
|
||||
* @summary REGRESSION: HttpURLConnection.getResponseCode() returns always -1
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
|
||||
public class getResponseCode {
|
||||
public static void main(String[] args) throws Exception {
|
||||
try {
|
||||
MyHttpURLConnectionImpl myCon = new MyHttpURLConnectionImpl(null);
|
||||
int responseCode = myCon.getResponseCode();
|
||||
if (responseCode == -1) {
|
||||
throw new RuntimeException("java.net.HttpURLConnection "
|
||||
+"should provide implementation "
|
||||
+"for getResponseCode()");
|
||||
}
|
||||
} catch (java.net.UnknownServiceException e) {
|
||||
System.out.println("PASS");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MyHttpURLConnectionImpl extends java.net.HttpURLConnection {
|
||||
MyHttpURLConnectionImpl(URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
public boolean usingProxy(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public void connect(){
|
||||
}
|
||||
|
||||
public void disconnect(){
|
||||
}
|
||||
}
|
||||
881
test/jdk/java/net/HugeDataTransferTest.java
Normal file
881
test/jdk/java/net/HugeDataTransferTest.java
Normal file
|
|
@ -0,0 +1,881 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8185072
|
||||
* @summary network006 times out in many configs in JDK10-hs nightly
|
||||
* @run main/othervm/manual HugeDataTransferTest 1
|
||||
*/
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* This test makes huge number of data transfers between 2 Java virtual machines
|
||||
* using the TCP/IP protocol, and checks if those data are transfered correctly.
|
||||
* Both client and server VMs run on the same local computer and attach TCP/IP
|
||||
* sockets to the local host, or to the loopback domain
|
||||
* ``<code>localhost</code>'' (having IP address <code>127.0.0.1</code>).
|
||||
*
|
||||
* <p>
|
||||
* In this test, 128 client/server connections are established. Once a
|
||||
* connection is established, client passes a data parcel to server, and server
|
||||
* reads that parcel and checks if it is same as expected (byte-to-byte equality
|
||||
* is desired). Then server passes (some other) parcel to the client, and client
|
||||
* reads and verifies those bytes. This ping-pong game is repeated 128 times;
|
||||
* and after that each pair of sockets checks if there are no extra bytes
|
||||
* accedentally passed through their connection.
|
||||
*
|
||||
* <p>
|
||||
* Parcels lengths and contents are chosen randomly, and average parcel length
|
||||
* is 128 bytes. So totally, each pair of sockets passes ~16Kb of data to each
|
||||
* other, and thus ~32Kb of data are transfered by each sockets pair. Totally,
|
||||
* ~4Mb of data are transfered by all client/server pairs.
|
||||
*
|
||||
* @author vtewari
|
||||
*/
|
||||
public class HugeDataTransferTest {
|
||||
|
||||
/**
|
||||
* Timeout for TCP/IP sockets (currently set to 1 min).
|
||||
*/
|
||||
private static int SO_TIMEOUT;// = 2*60*1000;
|
||||
|
||||
/**
|
||||
* Maximal number of connections this test should open simultaneously.
|
||||
*/
|
||||
private final static int MAX_CONNECTIONS = 128;
|
||||
|
||||
/**
|
||||
* Check few more connections to make sure that MAX_CONNECTIONS are safe.
|
||||
*/
|
||||
private final static int CONNECTIONS_RESERVE = 10;
|
||||
|
||||
/**
|
||||
* The test used to fail with connection reset by peer set to 50. (and once
|
||||
* in a three if it was set to 10). So now we set it to MAX_CONNECTIONS
|
||||
* (128).
|
||||
*/
|
||||
private final static int BACKLOG_QUEUE_LENGTH = MAX_CONNECTIONS;
|
||||
|
||||
/**
|
||||
* Number of parcels to be sent/recieved.
|
||||
*/
|
||||
private final static int DATA_PARCELS = 128;
|
||||
|
||||
/**
|
||||
* Maximal length of data parcel to be sent/recieved (it equals to 256 bytes
|
||||
* now).
|
||||
*/
|
||||
private final static int MAX_PARCEL = 1 << 8;
|
||||
|
||||
/**
|
||||
* Either actually display optional reports or not.
|
||||
*/
|
||||
static private final boolean DEBUG_MODE = false;
|
||||
|
||||
/**
|
||||
* How many IP sockets can we open simultaneously? Check if
|
||||
* <code>MAX_CONNECTIONS</code> connections can be open simultaneously.
|
||||
*/
|
||||
private static int detectOSLimitation() {
|
||||
final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE;
|
||||
display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:");
|
||||
|
||||
InetAddress address;
|
||||
ServerSocket serverSocket;
|
||||
try {
|
||||
address = InetAddress.getLocalHost();
|
||||
int anyPort = 0;
|
||||
int defaultBacklog = BACKLOG_QUEUE_LENGTH;
|
||||
serverSocket = new ServerSocket(anyPort, defaultBacklog, address);
|
||||
} catch (IOException ioe) {
|
||||
throw new Error("FATAL error while loading the test: " + ioe);
|
||||
}
|
||||
display(serverSocket.toString());
|
||||
|
||||
Socket server[] = new Socket[CONNECTIONS_TO_TRY];
|
||||
Socket client[] = new Socket[CONNECTIONS_TO_TRY];
|
||||
|
||||
int i, port = serverSocket.getLocalPort();
|
||||
for (i = 0; i < CONNECTIONS_TO_TRY; i++) {
|
||||
try {
|
||||
client[i] = new Socket(address, port);
|
||||
display(">Open: client[" + i + "] = " + client[i]);
|
||||
server[i] = serverSocket.accept();
|
||||
display(">Open: server[" + i + "] = " + server[i]);
|
||||
} catch (IOException ioe) {
|
||||
display(">OOPS! -- failed to open connection #" + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
display("> Could open "
|
||||
+ (i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections.");
|
||||
display(">Closing them:");
|
||||
for (int j = 0; j < i; j++) {
|
||||
try {
|
||||
server[j].close();
|
||||
client[j].close();
|
||||
} catch (IOException ioe) {
|
||||
throw new Error("FATAL error while loading the test: " + ioe);
|
||||
}
|
||||
}
|
||||
display(">OK.");
|
||||
int safeConnections = i - CONNECTIONS_RESERVE;
|
||||
if (safeConnections < 1) {
|
||||
safeConnections = 1;
|
||||
}
|
||||
if (safeConnections < MAX_CONNECTIONS) {
|
||||
complain("------------------------- CAUTION: -------------------");
|
||||
complain("While checking the OS limitations, the test found that");
|
||||
complain("only " + i + " TCP/IP socket connections could be safely open");
|
||||
complain("simultaneously. However, possibility to open at least");
|
||||
complain("" + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE
|
||||
+ " connections were expected.");
|
||||
complain("");
|
||||
complain("So, the test will check only " + safeConnections + " connection"
|
||||
+ (safeConnections == 1 ? "" : "s") + " which seem");
|
||||
complain("safe to be open simultaneously.");
|
||||
complain("------------------------------------------------------");
|
||||
}
|
||||
return safeConnections;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
/**
|
||||
* Re-calls to the method <code>run(args[],out)</code> actually performing
|
||||
* the test. After <code>run(args[],out)</code> stops, follow JDK-like
|
||||
* convention for exit codes. I.e.: stop with exit status 95 if the test has
|
||||
* passed, or with status 97 if the test has failed.
|
||||
*
|
||||
* @see #run(String[],PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
HugeDataTransferTest.out = out;
|
||||
|
||||
//
|
||||
// Get the Internet address of the local machine.
|
||||
//
|
||||
InetAddress address = null;
|
||||
try {
|
||||
address = InetAddress.getLocalHost();
|
||||
} catch (UnknownHostException exception) {
|
||||
complain(exception.toString());
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Host: " + address);
|
||||
|
||||
//
|
||||
// Detect if it is safe to open MAX_CONNETIONS simultaneously:
|
||||
//
|
||||
final int CONNECTIONS = detectOSLimitation();
|
||||
|
||||
//
|
||||
// Assign ServerSocket, and start client VM which should open
|
||||
// the prescribed number of CONNECTIONS to that ServerSocket.
|
||||
//
|
||||
ServerSocket serverSocket;
|
||||
try {
|
||||
final int anyPort = 0;
|
||||
final int defaultBacklog = BACKLOG_QUEUE_LENGTH;
|
||||
serverSocket = new ServerSocket(anyPort, defaultBacklog, address);
|
||||
} catch (IOException exception) {
|
||||
complain("Cannot assign a ServerSocket on: " + address);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Start the client process on different VM.
|
||||
//
|
||||
String jdkPath = System.getProperty("test.jdk");
|
||||
Path toolName = Paths.get("bin", "java" + (isWindows() ? ".exe" : ""));
|
||||
Path jdkTool = Paths.get(jdkPath, toolName.toString());
|
||||
|
||||
String IPAddress = address.getHostAddress();
|
||||
int localPort = serverSocket.getLocalPort();
|
||||
String arguments = " " + CONNECTIONS + " " + IPAddress + " " + localPort;
|
||||
//String command = args[0] + " " + network006.class.getName() + "$Client " + arguments;
|
||||
String command = jdkTool.toAbsolutePath().toString() + " " + Client.class.getName() + " " + arguments;
|
||||
try {
|
||||
SO_TIMEOUT = Integer.parseInt(args[0]) * 60 * 1000;
|
||||
} catch (NumberFormatException e) {
|
||||
complain("Wrong timeout argument: " + e);
|
||||
return 2;
|
||||
}
|
||||
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
|
||||
Process client = null;
|
||||
IORedirector redirectOut = null;
|
||||
IORedirector redirectErr = null;
|
||||
|
||||
try {
|
||||
// Start clients on different JVM:
|
||||
client = runtime.exec(command);
|
||||
|
||||
// Provide clients with access to stderr and stdout:
|
||||
InputStream clientOut = client.getInputStream();
|
||||
InputStream clientErr = client.getErrorStream();
|
||||
redirectOut = new IORedirector(clientOut, DEBUG_MODE ? out : null);
|
||||
redirectErr = new IORedirector(clientErr, out);
|
||||
redirectOut.start();
|
||||
redirectErr.start();
|
||||
|
||||
} catch (IOException exception) {
|
||||
complain("Failed to start client: " + exception);
|
||||
return 2;
|
||||
}
|
||||
//
|
||||
// Start the server threads (and let them establish connections):
|
||||
//
|
||||
|
||||
Server server[] = new Server[CONNECTIONS];
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
server[i] = new Server(serverSocket);
|
||||
display("Server #" + i + ": " + server[i]);
|
||||
server[i].start();
|
||||
}
|
||||
|
||||
//
|
||||
// Wait for the servers and the clients:
|
||||
//
|
||||
boolean testFailed = false;
|
||||
|
||||
try {
|
||||
client.waitFor();
|
||||
int clientStatus = client.exitValue();
|
||||
display("Client VM exitCode=" + clientStatus);
|
||||
|
||||
// Let I/O redirectors to flush:
|
||||
if (redirectOut.isAlive()) {
|
||||
redirectOut.join();
|
||||
}
|
||||
if (redirectErr.isAlive()) {
|
||||
redirectErr.join();
|
||||
}
|
||||
|
||||
// If client has crashed, also terminate the server (to avoid hangup).
|
||||
if (clientStatus != 95) {
|
||||
complain("Client VM has crashed: exit status=" + clientStatus);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
// Client has finished OK; wait for the server.
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
display("Server: waiting for #" + i);
|
||||
if (server[i].isAlive()) {
|
||||
display("Server #" + i + ": (joining...)" + server[i]);
|
||||
server[i].join();
|
||||
}
|
||||
if (server[i].exception != null) {
|
||||
if (server[i].message != null) {
|
||||
complain("Server #" + i + "(finished): with message:" + server[i].message);
|
||||
}
|
||||
|
||||
complain("Server #" + i + "(finished): " + server[i].exception);
|
||||
server[i].exception.printStackTrace(out);
|
||||
out.flush();
|
||||
// complain("Server #"+i+": "+server[i].exception.getStackTrace());
|
||||
testFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (InterruptedException exception) {
|
||||
complain("Test interrupted: " + exception);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
if (testFailed) {
|
||||
complain("Test failed.");
|
||||
} else {
|
||||
display("Test passed.");
|
||||
}
|
||||
return testFailed ? 2 : 0;
|
||||
}
|
||||
|
||||
private static boolean isWindows() {
|
||||
return System.getProperty("os.name").toLowerCase().startsWith("win");
|
||||
}
|
||||
//----------------------------------------------------------------//
|
||||
/**
|
||||
* Log stream for error messages and/or (optional) execution trace.
|
||||
*/
|
||||
private static PrintStream out;
|
||||
|
||||
/**
|
||||
* Print error message.
|
||||
*/
|
||||
private static synchronized void complain(Object message) {
|
||||
out.println("# " + message);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Display optional report: comment ca va?
|
||||
*/
|
||||
private static synchronized void display(Object report) {
|
||||
if (DEBUG_MODE) {
|
||||
out.println(report.toString());
|
||||
}
|
||||
out.flush(); //todo shouldn't this be inside if??
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Server thread should reply to data parcels sent by Client VM.
|
||||
*/
|
||||
private static class Server extends Thread {
|
||||
|
||||
/**
|
||||
* The socket is assigned at the Server instantiation.
|
||||
*/
|
||||
private ServerSocket serverSocket;
|
||||
|
||||
/**
|
||||
* The socket is assigned at the Server runtime.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* Display the server socket.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return "ServerSocket: " + serverSocket.toString();
|
||||
// + " socket: " + socket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Which port is this socket listening?
|
||||
*/
|
||||
int getPort() {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find some free port at the given <code>address</code> and attach new
|
||||
* server to hear that port. // lidsten to??
|
||||
*/
|
||||
public Server(ServerSocket serverSocket) {
|
||||
this.serverSocket = serverSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception just arisen while the server was working, or
|
||||
* <code>null</code> if it was OK with the server.
|
||||
*/
|
||||
Exception exception = null;
|
||||
String message = null;
|
||||
|
||||
/**
|
||||
* Accept connection, then reply to client's parcels.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
socket = serverSocket.accept();
|
||||
socket.setSoTimeout(SO_TIMEOUT);
|
||||
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(getPort());
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
message = "reading parcel number " + i;
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
complain("Server thread for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure( //received??
|
||||
"server has read unexpected parcel");
|
||||
}
|
||||
message = "sending parcel number " + i;
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
}
|
||||
|
||||
int datum = istream.read(); // wait for client close()
|
||||
if (datum >= 0) {
|
||||
throw new TestFailure(
|
||||
"server has read ambigous byte: " + datum);
|
||||
}
|
||||
|
||||
ostream.close(); // implies: socket.close();
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
/**
|
||||
* Client VM should send data parcels to Server VM and recieve and verify
|
||||
* the server's replies.
|
||||
*/
|
||||
private static class Client extends Thread {
|
||||
|
||||
/**
|
||||
* This thread uses the single client socket.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* Address and port of this socket.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return socket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the thread failed? If yes, what is the failure's reason.
|
||||
*/
|
||||
Exception exception = null;
|
||||
String message = null;
|
||||
|
||||
public static java.io.PrintStream complainStream = System.out;
|
||||
public static java.io.PrintStream displayStream = System.err;
|
||||
|
||||
/**
|
||||
* Connect client socket on the given <code>address</code> and
|
||||
* <code>port</code>.
|
||||
*/
|
||||
Client(InetAddress address, int port) throws IOException {
|
||||
socket = new Socket(address, port);
|
||||
socket.setSoTimeout(SO_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the port number this socket is listening for?
|
||||
*/
|
||||
int getPort() {
|
||||
return socket.getPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connection, then read/respond <code>DATA_PARCELS</code>
|
||||
* parcels of random data. Set initial seed for pseudo-random numbers
|
||||
* generator to the value of the local port number.
|
||||
*
|
||||
* @see #DATA_PARCELS
|
||||
* @see #getPort()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(getPort());
|
||||
// suggested by Oleg -- to avoid race conditions
|
||||
/* try{
|
||||
Thread.sleep(500);
|
||||
}
|
||||
catch (java.lang.InterruptedException e)
|
||||
{
|
||||
}*/
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
message = "sending parcel number: " + i;
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
|
||||
message = "reading parcel number: " + i;
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
complain("Client thread for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"parcel context is unexpected to client");
|
||||
}
|
||||
}
|
||||
|
||||
if (istream.available() > 0) {
|
||||
int datum = istream.read();
|
||||
throw new TestFailure(
|
||||
"client has read ambigous byte: " + datum);
|
||||
}
|
||||
ostream.close(); // implies: socket.close()
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish lots of connections to server socket, attack servers with
|
||||
* huge data parcels, and check if they reply correctly. The number of
|
||||
* connections to try, the address and port number for the server socket
|
||||
* are passed through <code>args[]</code>, like:
|
||||
* <pre>
|
||||
* java network006$Client connections_to_try address port
|
||||
* </pre>
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
if (DEBUG_MODE) {
|
||||
try {
|
||||
String filename = "Client" + ((args.length == 3) ? args[2] : "new");
|
||||
displayStream = new PrintStream(filename + ".out");
|
||||
complainStream = new PrintStream(filename + ".err");
|
||||
} catch (FileNotFoundException exception) {
|
||||
complain(exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (args.length != 3) {
|
||||
complain("Client expects 3 paramenets:");
|
||||
complain(" java " + Client.class.getName() + " connections_to_try address port");
|
||||
exit(1); // FAILED
|
||||
}
|
||||
|
||||
int CONNECTIONS = Integer.parseInt(args[0]);
|
||||
display("Client VM: will try " + CONNECTIONS + " connections.");
|
||||
InetAddress address;
|
||||
try {
|
||||
address = InetAddress.getByName(args[1]);
|
||||
} catch (UnknownHostException exception) {
|
||||
address = null;
|
||||
complain("Client: cannot find host: \"" + args[1] + "\"");
|
||||
exit(4);
|
||||
}
|
||||
display("Client: host to contact: " + address);
|
||||
int port = Integer.parseInt(args[2]);
|
||||
display("Client: port to contact: " + port);
|
||||
|
||||
//
|
||||
// Establish connections, and start client processes:
|
||||
//
|
||||
Client client[] = new Client[CONNECTIONS];
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
try {
|
||||
client[i] = new Client(address, port);
|
||||
display("Client #" + i + ": " + client[i]);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
complain("Client #" + i + "(creation): " + ioe);
|
||||
ioe.printStackTrace(complainStream);
|
||||
complainStream.flush();
|
||||
// complain("Client #" + i + "(creation): " + ioe.getStackTrace());
|
||||
exit(3);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
client[i].start();
|
||||
}
|
||||
|
||||
//
|
||||
// Wait until testing is not finished:
|
||||
//
|
||||
int status = 0;
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
display("Client: waiting for #" + i);
|
||||
if (client[i].isAlive()) {
|
||||
display("Client #" + i + ": (joining...)" + client[i]);
|
||||
|
||||
try {
|
||||
client[i].join();
|
||||
} catch (InterruptedException ie) {
|
||||
complain("Client #" + i + ": " + ie);
|
||||
status = 3;
|
||||
}
|
||||
}
|
||||
if (client[i].exception != null) {
|
||||
if (client[i].message != null) {
|
||||
complain("Client #" + i + "(finished) with message: " + client[i].message);
|
||||
}
|
||||
complain("Client #" + i + "(finished): " + client[i].exception);
|
||||
client[i].exception.printStackTrace(complainStream);
|
||||
complainStream.flush();
|
||||
if (status == 0) {
|
||||
status = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print error message.
|
||||
*/
|
||||
private static synchronized void complain(Object message) {
|
||||
complainStream.println("# " + message);
|
||||
complainStream.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display execution trace.
|
||||
*/
|
||||
private static synchronized void display(Object message) {
|
||||
if (!DEBUG_MODE) {
|
||||
return;
|
||||
}
|
||||
displayStream.println(message.toString());
|
||||
displayStream.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit with JCK-like status.
|
||||
*/
|
||||
private static void exit(int exitCode) {
|
||||
int status = exitCode + 95;
|
||||
// display("Client: exiting with code=" + status);
|
||||
System.exit(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Two of such threads should redirect <code>out</code> and <code>err</code>
|
||||
* streams of client VM.
|
||||
*/
|
||||
private static class IORedirector extends Thread {
|
||||
|
||||
/**
|
||||
* Source stream.
|
||||
*/
|
||||
InputStream in;
|
||||
/**
|
||||
* Destination stream.
|
||||
*/
|
||||
OutputStream out;
|
||||
|
||||
/**
|
||||
* Redirect <code>in</code> to <code>out</code>.
|
||||
*/
|
||||
public IORedirector(InputStream in, OutputStream out) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read input stream until the EOF, and write everithing to output
|
||||
* stream. If output stream is assigned to <code>null</code>, do not
|
||||
* print anything, but read the input stream anywhere.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (;;) {
|
||||
int symbol = in.read();
|
||||
if (symbol < 0) {
|
||||
break; // EOF
|
||||
}
|
||||
if (out != null) {
|
||||
out.write(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
if (out != null) {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
} catch (IOException exception) {
|
||||
throw new TestFailure("IORedirector exception: " + exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
/**
|
||||
* A data parcel to be sent/recieved between Client VM and Server thread.
|
||||
* When data parcel is sent, first 4 bytes are transfered which encode the
|
||||
* <code>int</code> number equal to size of the parcel minus 1. I.e.: if
|
||||
* number of data bytes in the parcel's contents is <code>N</code>, then the
|
||||
* first 4 bytes encode the number <code>N-1</code>. After that, the
|
||||
* parcel's contents bytes are transered.
|
||||
*/
|
||||
static class Parcel {
|
||||
|
||||
private final byte[] parcel;
|
||||
|
||||
/**
|
||||
* Display all bytes as integer values from 0 to 255; or return
|
||||
* ``<tt>null</tt>'' if this Parcel is not yet initialized.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (parcel == null) {
|
||||
return "null";
|
||||
}
|
||||
String s = "{";
|
||||
for (int i = 0; i < parcel.length; i++) {
|
||||
s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF);
|
||||
}
|
||||
return s + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new <code>parcel[]</code> array using the given
|
||||
* <code>random</code> numbers generator. Client and Server threads
|
||||
* should use identical <code>random</code> generators, so that those
|
||||
* threads could generate equal data parcels and check the parcel just
|
||||
* transfered.
|
||||
*/
|
||||
public Parcel(Random random) {
|
||||
int size = random.nextInt(MAX_PARCEL) + 1;
|
||||
parcel = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
parcel[i] = (byte) random.nextInt(256);
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Read exactly <code>size</code> bytes from the <code>istream</code>
|
||||
* if possible, or throw <code>TestFailure</code> if unexpected end of
|
||||
* <code>istream</code> occurs.
|
||||
*/
|
||||
private static byte[] readBytes(int size, InputStream istream)
|
||||
throws IOException {
|
||||
|
||||
byte data[] = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
int datum = istream.read();
|
||||
if (datum < 0) {
|
||||
throw new TestFailure(
|
||||
"unexpected EOF: have read: " + i + " bytes of " + size);
|
||||
}
|
||||
data[i] = (byte) datum;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 4 bytes from <code>istream</code> and threat them to encode size
|
||||
* of data parcel following these 4 bytes.
|
||||
*/
|
||||
private static int getSize(InputStream istream) throws IOException {
|
||||
byte data[] = readBytes(4, istream);
|
||||
int data0 = (int) data[0] & 0xFF;
|
||||
int data1 = (int) data[1] & 0xFF;
|
||||
int data2 = (int) data[2] & 0xFF;
|
||||
int data3 = (int) data[3] & 0xFF;
|
||||
int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24);
|
||||
int size = sizeWord + 1;
|
||||
if (size <= 0) {
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send 4 bytes encoding actual size of the parcel just to be
|
||||
* transfered.
|
||||
*/
|
||||
private static void putSize(OutputStream ostream, int size)
|
||||
throws IOException {
|
||||
|
||||
if (size <= 0) {
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
}
|
||||
|
||||
int sizeWord = size - 1;
|
||||
byte data[] = new byte[4];
|
||||
data[0] = (byte) sizeWord;
|
||||
data[1] = (byte) (sizeWord >> 8);
|
||||
data[2] = (byte) (sizeWord >> 16);
|
||||
data[3] = (byte) (sizeWord >> 24);
|
||||
ostream.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recieve data parcel.
|
||||
*/
|
||||
public Parcel(InputStream istream) throws IOException {
|
||||
int size = getSize(istream);
|
||||
parcel = readBytes(size, istream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send <code>this</code> data parcel.
|
||||
*/
|
||||
public void send(OutputStream ostream) throws IOException {
|
||||
int size = parcel.length;
|
||||
putSize(ostream, size);
|
||||
ostream.write(parcel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check byte-to-byte equality between <code>this</code> and the
|
||||
* <code>other</code> parcels.
|
||||
*/
|
||||
public boolean equals(Parcel other) {
|
||||
if (this.parcel.length != other.parcel.length) {
|
||||
return false;
|
||||
}
|
||||
int size = parcel.length;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (this.parcel[i] != other.parcel[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Server or Client may throw this exception to report the test failure.
|
||||
*/
|
||||
static class TestFailure extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Report particular <code>purpose</code> of the test failure.
|
||||
*/
|
||||
public TestFailure(String purpose) {
|
||||
super(purpose);
|
||||
}
|
||||
}
|
||||
}
|
||||
72
test/jdk/java/net/IDN/IllegalArg.java
Normal file
72
test/jdk/java/net/IDN/IllegalArg.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8020842
|
||||
* @summary IDN do not throw IAE when hostname ends with a trailing dot
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
public class IllegalArg {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String[] illegalNames = {
|
||||
"com..net",
|
||||
"com..",
|
||||
".com",
|
||||
".com."
|
||||
};
|
||||
|
||||
String[] legalNames = {
|
||||
"example.com",
|
||||
"com\u3002",
|
||||
"com.",
|
||||
"."
|
||||
};
|
||||
|
||||
for (String name : illegalNames) {
|
||||
try {
|
||||
IDN.toASCII(name, IDN.USE_STD3_ASCII_RULES);
|
||||
throw new Exception(
|
||||
"Expected to get IllegalArgumentException for " + name);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// That's the right behavior.
|
||||
}
|
||||
|
||||
try {
|
||||
IDN.toASCII(name);
|
||||
throw new Exception(
|
||||
"Expected to get IllegalArgumentException for " + name);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// That's the right behavior.
|
||||
}
|
||||
}
|
||||
|
||||
for (String name : legalNames) {
|
||||
System.out.println("Convering " + name);
|
||||
System.out.println(IDN.toASCII(name, IDN.USE_STD3_ASCII_RULES));
|
||||
}
|
||||
}
|
||||
}
|
||||
80
test/jdk/java/net/IDN/UseSTD3ASCIIRules.java
Normal file
80
test/jdk/java/net/IDN/UseSTD3ASCIIRules.java
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8023881
|
||||
* @summary IDN.USE_STD3_ASCII_RULES option is too strict to use Unicode
|
||||
* in IDN.toASCII
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
public class UseSTD3ASCIIRules {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Per Section 4.1, RFC 3490, if the UseSTD3ASCIIRules flag is set,
|
||||
// then perform these checks:
|
||||
//
|
||||
// (a) Verify the absence of non-LDH ASCII code points; that is, the
|
||||
// absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F.
|
||||
//
|
||||
// (b) Verify the absence of leading and trailing hyphen-minus; that
|
||||
// is, the absence of U+002D at the beginning and end of the
|
||||
// sequence.
|
||||
String[] illegalNames = {
|
||||
"www.example.com-",
|
||||
"-www.example.com",
|
||||
"-www.example.com-",
|
||||
"www.ex\u002Cmple.com",
|
||||
"www.ex\u007Bmple.com",
|
||||
"www.ex\u007Fmple.com"
|
||||
};
|
||||
|
||||
String[] legalNames = {
|
||||
"www.ex-ample.com",
|
||||
"www.ex\u002Dmple.com", // www.ex-mple.com
|
||||
"www.ex\u007Ample.com", // www.exzmple.com
|
||||
"www.ex\u3042mple.com", // www.xn--exmple-j43e.com
|
||||
"www.\u3042\u3044\u3046.com", // www.xn--l8jeg.com
|
||||
"www.\u793A\u4F8B.com" // www.xn--fsq092h.com
|
||||
};
|
||||
|
||||
for (String name : illegalNames) {
|
||||
try {
|
||||
System.out.println("Convering illegal IDN: " + name);
|
||||
IDN.toASCII(name, IDN.USE_STD3_ASCII_RULES);
|
||||
throw new Exception(
|
||||
"Expected to get IllegalArgumentException for " + name);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// That's the right behavior.
|
||||
}
|
||||
}
|
||||
|
||||
for (String name : legalNames) {
|
||||
System.out.println("Convering legal IDN: " + name);
|
||||
System.out.println("\tThe ACE form is: " +
|
||||
IDN.toASCII(name, IDN.USE_STD3_ASCII_RULES));
|
||||
}
|
||||
}
|
||||
}
|
||||
48
test/jdk/java/net/IDNTest.java
Normal file
48
test/jdk/java/net/IDNTest.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2024, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.net.IDN;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 7038838
|
||||
* @summary verify the behaviour of the methods on java.net.IDN class
|
||||
* @run junit IDNTest
|
||||
*/
|
||||
public class IDNTest {
|
||||
|
||||
/*
|
||||
* Verify that various methods on the IDN class throw a NullPointerException
|
||||
* for any null parameter.
|
||||
*/
|
||||
@Test
|
||||
public void testNullPointerException() throws Exception {
|
||||
assertThrows(NullPointerException.class, () -> IDN.toASCII(null));
|
||||
assertThrows(NullPointerException.class, () -> IDN.toASCII(null, 0));
|
||||
assertThrows(NullPointerException.class, () -> IDN.toUnicode(null));
|
||||
assertThrows(NullPointerException.class, () -> IDN.toUnicode(null, 0));
|
||||
}
|
||||
}
|
||||
70
test/jdk/java/net/Inet4Address/PingThis.java
Normal file
70
test/jdk/java/net/Inet4Address/PingThis.java
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2025, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 2012 IBM Corporation
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 7163874 8133015
|
||||
* @summary InetAddress.isReachable is returning false for InetAdress 0.0.0.0 and ::0
|
||||
* @requires os.family != "windows"
|
||||
* @library /test/lib
|
||||
* @run main PingThis
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true PingThis
|
||||
*/
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
public class PingThis {
|
||||
public static void main(String args[]) throws Exception {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
|
||||
List<String> addrs = new ArrayList<String>();
|
||||
|
||||
if (IPSupport.hasIPv4()) {
|
||||
addrs.add("0.0.0.0");
|
||||
}
|
||||
if (IPSupport.hasIPv6()) {
|
||||
addrs.add("::0");
|
||||
}
|
||||
|
||||
for (String addr : addrs) {
|
||||
InetAddress inetAddress = InetAddress.getByName(addr);
|
||||
System.out.println("The target ip is "
|
||||
+ inetAddress.getHostAddress());
|
||||
boolean isReachable = inetAddress.isReachable(3000);
|
||||
System.out.println("the target is reachable: " + isReachable);
|
||||
if (isReachable) {
|
||||
System.out.println("Test passed ");
|
||||
} else {
|
||||
System.out.println("Test failed ");
|
||||
throw new Exception("address " + inetAddress.getHostAddress()
|
||||
+ " can not be reachable!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
62
test/jdk/java/net/Inet4Address/isSiteLocalAddress.java
Normal file
62
test/jdk/java/net/Inet4Address/isSiteLocalAddress.java
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4670299
|
||||
* @summary Inet4Address.isSiteLocalAddress() is broken against RFC 1918
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class isSiteLocalAddress {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String[][] addrs =
|
||||
{{"9.255.255.255", "false"}, {"10.0.0.0", "true"},
|
||||
{"10.255.255.255", "true"}, {"11.0.0.0", "false"},
|
||||
{"172.15.255.255", "false"}, {"172.16.0.0", "true"},
|
||||
{"172.30.1.2", "true"}, {"172.31.255.255", "true"},
|
||||
{"172.32.0.0", "false"}, {"192.167.255.255", "false"},
|
||||
{"192.168.0.0", "true"}, {"192.168.255.255", "true"},
|
||||
{"192.169.0.0", "false"}};
|
||||
|
||||
Vector v = new Vector();
|
||||
for (int i = 0; i < addrs.length; i++) {
|
||||
InetAddress addr = InetAddress.getByName(addrs[i][0]);
|
||||
boolean result = new Boolean(addrs[i][1]).booleanValue();
|
||||
if (addr.isSiteLocalAddress() != result) {
|
||||
v.add(addrs[i]);
|
||||
}
|
||||
}
|
||||
Iterator itr = v.iterator();
|
||||
while (itr.hasNext()) {
|
||||
String[] entry = (String[]) itr.next();
|
||||
System.out.println(entry[0] +" should return "+entry[1]
|
||||
+ " when calling isSiteLocalAddress()");
|
||||
}
|
||||
if (v.size() > 0) {
|
||||
throw new RuntimeException("InetAddress.isSiteLocalAddress() test failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
105
test/jdk/java/net/Inet4Address/textToNumericFormat.java
Normal file
105
test/jdk/java/net/Inet4Address/textToNumericFormat.java
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4749938 8087190
|
||||
* @summary Bug in the parsing IPv4 literal addresses
|
||||
* @run main/othervm -Djdk.net.hosts.file=HostFileDoesNotExist textToNumericFormat
|
||||
*/
|
||||
|
||||
/**
|
||||
* We use a dummy name service which throws UHE any time it is called.
|
||||
* We do this because the "good" tests here should parse correctly
|
||||
* without needing to call the name service, and the bad tests will
|
||||
* not parse and then invoke the name service, where we expect
|
||||
* the exception.
|
||||
*/
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.*;
|
||||
|
||||
public class textToNumericFormat {
|
||||
|
||||
public static void main(String[] args) throws UnknownHostException {
|
||||
List<String> goodList = new ArrayList<>();
|
||||
List<String> badList = new ArrayList<>();
|
||||
String goodAddrs[] = {
|
||||
"224.0.1.0",
|
||||
"238.255.255.255",
|
||||
"239.255.255.255",
|
||||
"239.255.65535",
|
||||
"239.16777215",
|
||||
"4294967295" };
|
||||
|
||||
String badAddrs[] = {
|
||||
"238.255.255.2550",
|
||||
"256.255.255.255",
|
||||
"238.255.2550.255",
|
||||
"238.2550.255.255",
|
||||
"2380.255.255.255",
|
||||
"239.255.65536",
|
||||
"239.16777216",
|
||||
"4294967296",
|
||||
".1.1.1",
|
||||
"1..1.1",
|
||||
"1.1.1.",
|
||||
"..." };
|
||||
|
||||
for (int i=0; i<goodAddrs.length; i++) {
|
||||
try {
|
||||
// Value is an IP Address literal, Name Service will not be called
|
||||
InetAddress ia = InetAddress.getByName(goodAddrs[i]);
|
||||
} catch (UnknownHostException e) {
|
||||
// shouldn't have come here
|
||||
goodList.add(goodAddrs[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i=0; i<badAddrs.length; i++) {
|
||||
try {
|
||||
// Value is not an IP Address literal, Name Service will be called
|
||||
InetAddress ia = InetAddress.getByName(badAddrs[i]);
|
||||
// shouldn't have come here
|
||||
badList.add(badAddrs[i]);
|
||||
} catch (UnknownHostException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if either goodList or badList is not empty, throw exception
|
||||
if (goodList.size() > 0 || badList.size() > 0) {
|
||||
throw new RuntimeException((goodList.size() > 0?
|
||||
("Good address not parsed: "+ goodList)
|
||||
: "") +
|
||||
(badList.size() > 0 ?
|
||||
("Bad Address parsed: "+ badList)
|
||||
: ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
55
test/jdk/java/net/Inet6Address/B4923906.java
Normal file
55
test/jdk/java/net/Inet6Address/B4923906.java
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4923906
|
||||
* @summary Inet6Address.getScopedInterface() returns a String instead of a NetworkInterface
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class B4923906 {
|
||||
public static void main (String[] args) throws Exception {
|
||||
Enumeration e = NetworkInterface.getNetworkInterfaces();
|
||||
while (e.hasMoreElements()) {
|
||||
NetworkInterface ifc = (NetworkInterface) e.nextElement();
|
||||
Enumeration addrs = ifc.getInetAddresses();
|
||||
System.out.println (ifc.getName() +": " + ifc.getDisplayName());
|
||||
while (addrs.hasMoreElements()) {
|
||||
InetAddress a = (InetAddress)addrs.nextElement();
|
||||
System.out.println ("\t"+a);
|
||||
if (a instanceof Inet6Address) {
|
||||
Inet6Address ia6 = (Inet6Address) a;
|
||||
Object o = ia6.getScopedInterface();
|
||||
if (o instanceof String) {
|
||||
throw new RuntimeException (
|
||||
"Oops! This should be a NetworkInterface"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
71
test/jdk/java/net/Inet6Address/B6206527.java
Normal file
71
test/jdk/java/net/Inet6Address/B6206527.java
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2021, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test 1.1 05/01/05
|
||||
* @bug 6206527
|
||||
* @summary "cannot assign address" when binding ServerSocket on Suse 9
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* @run main B6206527
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
|
||||
public class B6206527 {
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
Inet6Address addr = getLocalAddr();
|
||||
if (addr == null) {
|
||||
System.out.println("Could not find a link-local address");
|
||||
return;
|
||||
}
|
||||
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
System.out.println("trying LL addr: " + addr);
|
||||
ss.bind(new InetSocketAddress(addr, 0));
|
||||
}
|
||||
|
||||
// need to remove the %scope suffix
|
||||
addr = (Inet6Address) InetAddress.getByAddress (
|
||||
addr.getAddress()
|
||||
);
|
||||
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
System.out.println("trying LL addr: " + addr);
|
||||
ss.bind(new InetSocketAddress(addr, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public static Inet6Address getLocalAddr() throws Exception {
|
||||
Optional<Inet6Address> oaddr = NetworkConfiguration.probe()
|
||||
.ip6Addresses()
|
||||
.filter(a -> a.isLinkLocalAddress())
|
||||
.findFirst();
|
||||
|
||||
return oaddr.orElseGet(() -> null);
|
||||
}
|
||||
}
|
||||
93
test/jdk/java/net/Inet6Address/B6558853.java
Normal file
93
test/jdk/java/net/Inet6Address/B6558853.java
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key intermittent
|
||||
* @bug 6558853
|
||||
* @summary getHostAddress() on connections using IPv6 link-local addrs should have zone id
|
||||
* This test needs to bind to the wildcard address and as such is succeptible to
|
||||
* fail intermittently because of port reuse issues.
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* @run main B6558853
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.*;
|
||||
import java.util.Optional;
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
|
||||
public class B6558853 implements Runnable {
|
||||
private InetAddress addr = null;
|
||||
private int port = 0;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Optional<Inet6Address> oaddr = NetworkConfiguration.probe()
|
||||
.ip6Addresses()
|
||||
.filter(a -> a.isLinkLocalAddress())
|
||||
.findFirst();
|
||||
|
||||
if (!oaddr.isPresent()) {
|
||||
System.out.println("No suitable interface found. Exiting.");
|
||||
return;
|
||||
}
|
||||
|
||||
Inet6Address dest = oaddr.get();
|
||||
System.out.println("Using " + dest);
|
||||
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
int port = ss.getLocalPort();
|
||||
B6558853 test = new B6558853(dest, port);
|
||||
Thread thread = new Thread(test);
|
||||
thread.start();
|
||||
Socket s = ss.accept();
|
||||
InetAddress a = s.getInetAddress();
|
||||
OutputStream out = s.getOutputStream();
|
||||
out.write(1);
|
||||
out.close();
|
||||
if (!(a instanceof Inet6Address) || a.getHostAddress().indexOf("%") == -1) {
|
||||
// No Scope found in the address String
|
||||
throw new RuntimeException("Wrong address: " + a.getHostAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public B6558853(InetAddress a, int port) {
|
||||
addr = a;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
Socket s = new Socket(addr, port);
|
||||
InputStream in = s.getInputStream();
|
||||
int i = in.read();
|
||||
in.close();
|
||||
} catch (IOException iOException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
69
test/jdk/java/net/Inet6Address/IPv6AddressTypes.java
Normal file
69
test/jdk/java/net/Inet6Address/IPv6AddressTypes.java
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4482124
|
||||
* @summary Inet6Address.isLinkLocal() and isSiteLocal()
|
||||
* implementation incorrect
|
||||
*
|
||||
*/
|
||||
import java.net.*;
|
||||
|
||||
public class IPv6AddressTypes {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String[] goodlinklocal = {"fe80::a00:20ff:feae:45c9",
|
||||
"fe80::", "feb0::"};
|
||||
String[] badlinklocal = {"fec0::", "fe70::", "ff00::"};
|
||||
String[] goodsitelocal = {"fec0::a00:20ff:feae:45c9", "feff::"};
|
||||
String[] badsitelocal = {"fe80::", "fe00::", "ffc0::"};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < goodlinklocal.length; i++) {
|
||||
InetAddress ia = InetAddress.getByName(goodlinklocal[i]);
|
||||
if (!ia.isLinkLocalAddress()) {
|
||||
throw new RuntimeException("Link-local address check failed:"+ia);
|
||||
} else {
|
||||
System.out.println("succeed: "+ia);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < badlinklocal.length; i++) {
|
||||
InetAddress ia = InetAddress.getByName(badlinklocal[i]);
|
||||
if (ia.isLinkLocalAddress()) {
|
||||
throw new RuntimeException("Link-local address check failed:"+ia);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < goodsitelocal.length; i++) {
|
||||
InetAddress ia = InetAddress.getByName(goodsitelocal[i]);
|
||||
if (!ia.isSiteLocalAddress()) {
|
||||
throw new RuntimeException("Site-local address check failed:"+ia);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < badsitelocal.length; i++) {
|
||||
InetAddress ia = InetAddress.getByName(badsitelocal[i]);
|
||||
if (ia.isSiteLocalAddress()) {
|
||||
throw new RuntimeException("Site-local address check failed:"+ia);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue