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:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View 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();
}
}
}

View 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);
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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;
}
}
}

View 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()));
}
}
}

View 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()));
}
}
}

View 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");
}
}
}

View 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 ();
}
}
}

View 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");
}
}
}
}

View 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 ();
}
}
}

View 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");
}
}
}
}

View 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();
}
}
}

View 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);
}
}

View 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();
}
}

View 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");
}
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}
}

View 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");
}
}
}
}

View 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;
}
}

View 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) { }
}
}

View 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();
}
}
}
}

View 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);
}
}
}

View 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.");
}
}

View 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));
}
}
}

View 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!");
}
}

View 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);
}
}

View 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);
}
}

View 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");
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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");
}
}

View 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);
}
}

View 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;
}
}
}

View 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();
}
}
}

View 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) {
}
}
}
}

View 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();
}
}

View 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());
}
}
}

View 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);
}
}
}
}

View 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;
}
}
}
}

View 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());
}
}

View 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) { }
}
}

View 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();
}
}

View 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;
}
}
}
}
}
}

View file

@ -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);
}
}
}

View 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(); }
}
}
}

View 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(); }
}
}

View 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);
}
}
}
}

View 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;
}
}
}

View 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");
}
}

View 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");
}
}
}
}

View 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();
}
}
}

View 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");
}
}
}

View 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();
}
}

View 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);
}
}
}
}
}

View 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(); }
}
}
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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);
}
}

View 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);
}
}

View 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));
}
}
}

View 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++;
}
}
}

View file

@ -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();
}
}
}

View 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();
}
}
}

View 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; }
}
}

View 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; }
}
}

View 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");
}
}
}

View 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");
}
}
}
}

View 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);
}
}
}

View file

@ -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 {
}

View file

@ -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);
}
}

View 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);
}
}
}
}

View 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();
}
}

View 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() {
}
}

View 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();
}
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}
}

View file

@ -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);
}
}
}

View file

@ -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();
}
}

View 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
}
}
}

View 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());
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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

View 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");}
}

View 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(){
}
}

View 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);
}
}
}

View 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));
}
}
}

View 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));
}
}
}

View 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));
}
}

View 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!");
}
}
}
}

View 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");
}
}
}

View 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)
: ""));
}
}
}

View 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"
);
}
}
}
}
}
}

View 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);
}
}

View 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) {
}
}
}

View 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