mirror of
https://github.com/darlinghq/darling-openjdk.git
synced 2024-11-27 14:20:27 +00:00
8221481: Reimplement the Legacy Socket API
Reviewed-by: michaelm, chegar
This commit is contained in:
parent
23be0f0c2a
commit
7e14aeb133
@ -25,33 +25,63 @@
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileDescriptor;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.net.NetProperties;
|
||||
import sun.net.PlatformSocketImpl;
|
||||
import sun.nio.ch.NioSocketImpl;
|
||||
|
||||
/**
|
||||
* The abstract class {@code SocketImpl} is a common superclass
|
||||
* of all classes that actually implement sockets. It is used to
|
||||
* create both client and server sockets.
|
||||
* <p>
|
||||
* A "plain" socket implements these methods exactly as
|
||||
* described, without attempting to go through a firewall or proxy.
|
||||
*
|
||||
* @implNote Client and server sockets created with the {@code Socket} and
|
||||
* {@code SocketServer} public constructors create a system-default
|
||||
* {@code SocketImpl}. The JDK historically used a {@code SocketImpl}
|
||||
* implementation type named "PlainSocketImpl" that has since been replaced by a
|
||||
* newer implementation. The JDK continues to ship with the older implementation
|
||||
* to allow code to run that depends on unspecified behavior that differs between
|
||||
* the old and new implementations. The old implementation will be used if the
|
||||
* Java virtual machine is started with the system property {@systemProperty
|
||||
* jdk.net.usePlainSocketImpl} set to use the old implementation. It may also be
|
||||
* set in the JDK's network configuration file, located in {@code
|
||||
* ${java.home}/conf/net.properties}. The value of the property is the string
|
||||
* representation of a boolean. If set without a value then it defaults to {@code
|
||||
* true}, hence running with {@code -Djdk.net.usePlainSocketImpl} or {@code
|
||||
* -Djdk.net.usePlainSocketImpl=true} will configure the Java virtual machine
|
||||
* to use the old implementation. The property and old implementation will be
|
||||
* removed in a future version.
|
||||
*
|
||||
* @author unascribed
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract class SocketImpl implements SocketOptions {
|
||||
private static final boolean USE_PLAINSOCKETIMPL = usePlainSocketImpl();
|
||||
|
||||
private static boolean usePlainSocketImpl() {
|
||||
PrivilegedAction<String> pa = () -> NetProperties.get("jdk.net.usePlainSocketImpl");
|
||||
String s = AccessController.doPrivileged(pa);
|
||||
return (s != null) && !s.equalsIgnoreCase("false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of platform's SocketImpl
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
|
||||
return (S) new PlainSocketImpl(server);
|
||||
if (USE_PLAINSOCKETIMPL) {
|
||||
return (S) new PlainSocketImpl(server);
|
||||
} else {
|
||||
return (S) new NioSocketImpl(server);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
1283
src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java
Normal file
1283
src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -600,6 +600,9 @@ java/net/DatagramSocket/SendDatagramToBadAddress.java 7143960 macosx-a
|
||||
|
||||
java/net/ServerSocket/AcceptInheritHandle.java 8211854 aix-ppc64
|
||||
|
||||
java/net/Inet6Address/B6206527.java 8216417 macosx-all
|
||||
java/net/ipv6tests/B6521014.java 8216417 macosx-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_nio
|
||||
@ -862,6 +865,7 @@ javax/rmi/ssl/SSLSocketParametersTest.sh 8162906 generic-
|
||||
jdk/jfr/event/io/TestInstrumentation.java 8202142 generic-all
|
||||
jdk/jfr/api/recording/event/TestPeriod.java 8215890 generic-all
|
||||
|
||||
jdk/jfr/event/io/EvilInstrument.java 8221331 generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -27,6 +27,7 @@
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.net.SimpleSSLContext
|
||||
* @run main/othervm Test1
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl Test1
|
||||
* @run main/othervm -Dsun.net.httpserver.maxReqTime=10 Test1
|
||||
* @run main/othervm -Dsun.net.httpserver.nodelay=true Test1
|
||||
* @summary Light weight HTTP server
|
||||
|
@ -38,6 +38,7 @@
|
||||
* jdk.test.lib.process.*
|
||||
* AcceptCauseFileDescriptorLeak
|
||||
* @run main/othervm AcceptCauseFileDescriptorLeak root
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl AcceptCauseFileDescriptorLeak root
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -27,6 +27,7 @@
|
||||
* @modules java.management java.base/java.io:+open java.base/java.net:+open
|
||||
* @run main/othervm UnreferencedSockets
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true UnreferencedSockets
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl UnreferencedSockets
|
||||
* @summary Check that unreferenced sockets are closed
|
||||
*/
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
* @test
|
||||
* @requires os.family != "solaris"
|
||||
* @run testng ConnectionReset
|
||||
* @run testng/othervm -Djdk.net.usePlainSocketImpl ConnectionReset
|
||||
* @summary Test behavior of read and available when a connection is reset
|
||||
*/
|
||||
|
||||
|
@ -23,9 +23,10 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8221481
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Utils
|
||||
* @run testng Timeouts
|
||||
* @run testng/timeout=180 Timeouts
|
||||
* @summary Test Socket timeouts
|
||||
*/
|
||||
|
||||
@ -34,12 +35,17 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -54,7 +60,7 @@ public class Timeouts {
|
||||
* Test timed connect where connection is established
|
||||
*/
|
||||
public void testTimedConnect1() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
try (Socket s = new Socket()) {
|
||||
s.connect(ss.getLocalSocketAddress(), 2000);
|
||||
}
|
||||
@ -77,7 +83,7 @@ public class Timeouts {
|
||||
* Test connect with a timeout of Integer.MAX_VALUE
|
||||
*/
|
||||
public void testTimedConnect3() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
try (Socket s = new Socket()) {
|
||||
s.connect(ss.getLocalSocketAddress(), Integer.MAX_VALUE);
|
||||
}
|
||||
@ -88,12 +94,10 @@ public class Timeouts {
|
||||
* Test connect with a negative timeout.
|
||||
*/
|
||||
public void testTimedConnect4() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
try (Socket s = new Socket()) {
|
||||
try {
|
||||
s.connect(ss.getLocalSocketAddress(), -1);
|
||||
assertTrue(false);
|
||||
} catch (IllegalArgumentException expected) { }
|
||||
expectThrows(IllegalArgumentException.class,
|
||||
() -> s.connect(ss.getLocalSocketAddress(), -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,10 +132,10 @@ public class Timeouts {
|
||||
public void testTimedRead3() throws IOException {
|
||||
withConnection((s1, s2) -> {
|
||||
s2.setSoTimeout(2000);
|
||||
try {
|
||||
s2.getInputStream().read();
|
||||
assertTrue(false);
|
||||
} catch (SocketTimeoutException expected) { }
|
||||
long startMillis = millisTime();
|
||||
expectThrows(SocketTimeoutException.class, () -> s2.getInputStream().read());
|
||||
int timeout = s2.getSoTimeout();
|
||||
checkDuration(startMillis, timeout-100, timeout+2000);
|
||||
});
|
||||
}
|
||||
|
||||
@ -141,10 +145,7 @@ public class Timeouts {
|
||||
public void testTimedRead4() throws IOException {
|
||||
withConnection((s1, s2) -> {
|
||||
s2.setSoTimeout(2000);
|
||||
try {
|
||||
s2.getInputStream().read();
|
||||
assertTrue(false);
|
||||
} catch (SocketTimeoutException e) { }
|
||||
expectThrows(SocketTimeoutException.class, () -> s2.getInputStream().read());
|
||||
s1.getOutputStream().write(99);
|
||||
int b = s2.getInputStream().read();
|
||||
assertTrue(b == 99);
|
||||
@ -158,10 +159,7 @@ public class Timeouts {
|
||||
public void testTimedRead5() throws IOException {
|
||||
withConnection((s1, s2) -> {
|
||||
s2.setSoTimeout(2000);
|
||||
try {
|
||||
s2.getInputStream().read();
|
||||
assertTrue(false);
|
||||
} catch (SocketTimeoutException e) { }
|
||||
expectThrows(SocketTimeoutException.class, () -> s2.getInputStream().read());
|
||||
s2.setSoTimeout(30*3000);
|
||||
scheduleWrite(s1.getOutputStream(), 99, 2000);
|
||||
int b = s2.getInputStream().read();
|
||||
@ -175,10 +173,7 @@ public class Timeouts {
|
||||
public void testTimedRead6() throws IOException {
|
||||
withConnection((s1, s2) -> {
|
||||
s2.setSoTimeout(2000);
|
||||
try {
|
||||
s2.getInputStream().read();
|
||||
assertTrue(false);
|
||||
} catch (SocketTimeoutException e) { }
|
||||
expectThrows(SocketTimeoutException.class, () -> s2.getInputStream().read());
|
||||
s1.getOutputStream().write(99);
|
||||
s2.setSoTimeout(0);
|
||||
int b = s2.getInputStream().read();
|
||||
@ -193,10 +188,7 @@ public class Timeouts {
|
||||
public void testTimedRead7() throws IOException {
|
||||
withConnection((s1, s2) -> {
|
||||
s2.setSoTimeout(2000);
|
||||
try {
|
||||
s2.getInputStream().read();
|
||||
assertTrue(false);
|
||||
} catch (SocketTimeoutException e) { }
|
||||
expectThrows(SocketTimeoutException.class, () -> s2.getInputStream().read());
|
||||
scheduleWrite(s1.getOutputStream(), 99, 2000);
|
||||
s2.setSoTimeout(0);
|
||||
int b = s2.getInputStream().read();
|
||||
@ -211,10 +203,7 @@ public class Timeouts {
|
||||
withConnection((s1, s2) -> {
|
||||
s2.setSoTimeout(30*1000);
|
||||
scheduleClose(s2, 2000);
|
||||
try {
|
||||
s2.getInputStream().read();
|
||||
assertTrue(false);
|
||||
} catch (SocketException expected) { }
|
||||
expectThrows(SocketException.class, () -> s2.getInputStream().read());
|
||||
});
|
||||
}
|
||||
|
||||
@ -280,7 +269,7 @@ public class Timeouts {
|
||||
public void testTimedAccept1() throws IOException {
|
||||
Socket s1 = null;
|
||||
Socket s2 = null;
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
s1 = new Socket();
|
||||
s1.connect(ss.getLocalSocketAddress());
|
||||
ss.setSoTimeout(30*1000);
|
||||
@ -295,7 +284,7 @@ public class Timeouts {
|
||||
* Test timed accept where a connection is established after a short delay
|
||||
*/
|
||||
public void testTimedAccept2() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(30*1000);
|
||||
scheduleConnect(ss.getLocalSocketAddress(), 2000);
|
||||
Socket s = ss.accept();
|
||||
@ -307,13 +296,17 @@ public class Timeouts {
|
||||
* Test timed accept where the accept times out
|
||||
*/
|
||||
public void testTimedAccept3() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(2000);
|
||||
long startMillis = millisTime();
|
||||
try {
|
||||
Socket s = ss.accept();
|
||||
s.close();
|
||||
assertTrue(false);
|
||||
} catch (SocketTimeoutException expected) { }
|
||||
fail();
|
||||
} catch (SocketTimeoutException expected) {
|
||||
int timeout = ss.getSoTimeout();
|
||||
checkDuration(startMillis, timeout-100, timeout+2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,12 +315,12 @@ public class Timeouts {
|
||||
* previous accept timed out.
|
||||
*/
|
||||
public void testTimedAccept4() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(2000);
|
||||
try {
|
||||
Socket s = ss.accept();
|
||||
s.close();
|
||||
assertTrue(false);
|
||||
fail();
|
||||
} catch (SocketTimeoutException expected) { }
|
||||
try (Socket s1 = new Socket()) {
|
||||
s1.connect(ss.getLocalSocketAddress());
|
||||
@ -342,12 +335,12 @@ public class Timeouts {
|
||||
* accept timed out
|
||||
*/
|
||||
public void testTimedAccept5() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(2000);
|
||||
try {
|
||||
Socket s = ss.accept();
|
||||
s.close();
|
||||
assertTrue(false);
|
||||
fail();
|
||||
} catch (SocketTimeoutException expected) { }
|
||||
ss.setSoTimeout(0);
|
||||
try (Socket s1 = new Socket()) {
|
||||
@ -363,12 +356,12 @@ public class Timeouts {
|
||||
* accept timed out and after a short delay
|
||||
*/
|
||||
public void testTimedAccept6() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(2000);
|
||||
try {
|
||||
Socket s = ss.accept();
|
||||
s.close();
|
||||
assertTrue(false);
|
||||
fail();
|
||||
} catch (SocketTimeoutException expected) { }
|
||||
ss.setSoTimeout(0);
|
||||
scheduleConnect(ss.getLocalSocketAddress(), 2000);
|
||||
@ -381,13 +374,134 @@ public class Timeouts {
|
||||
* Test async close of a timed accept
|
||||
*/
|
||||
public void testTimedAccept7() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(30*1000);
|
||||
scheduleClose(ss, 2000);
|
||||
long delay = 2000;
|
||||
scheduleClose(ss, delay);
|
||||
long startMillis = millisTime();
|
||||
try {
|
||||
ss.accept().close();
|
||||
assertTrue(false);
|
||||
} catch (SocketException expected) { }
|
||||
fail();
|
||||
} catch (SocketException expected) {
|
||||
checkDuration(startMillis, delay-100, delay+2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test timed accept with the thread interrupt status set.
|
||||
*/
|
||||
public void testTimedAccept8() throws IOException {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(2000);
|
||||
Thread.currentThread().interrupt();
|
||||
long startMillis = millisTime();
|
||||
try {
|
||||
Socket s = ss.accept();
|
||||
s.close();
|
||||
fail();
|
||||
} catch (SocketTimeoutException expected) {
|
||||
// accept should have blocked for 2 seconds
|
||||
int timeout = ss.getSoTimeout();
|
||||
checkDuration(startMillis, timeout-100, timeout+2000);
|
||||
assertTrue(Thread.currentThread().isInterrupted());
|
||||
} finally {
|
||||
Thread.interrupted(); // clear interrupt status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test interrupt of thread blocked in timed accept.
|
||||
*/
|
||||
public void testTimedAccept9() throws IOException {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(4000);
|
||||
// interrupt thread after 1 second
|
||||
Future<?> interrupter = scheduleInterrupt(Thread.currentThread(), 1000);
|
||||
long startMillis = millisTime();
|
||||
try {
|
||||
Socket s = ss.accept(); // should block for 4 seconds
|
||||
s.close();
|
||||
fail();
|
||||
} catch (SocketTimeoutException expected) {
|
||||
// accept should have blocked for 4 seconds
|
||||
int timeout = ss.getSoTimeout();
|
||||
checkDuration(startMillis, timeout-100, timeout+2000);
|
||||
assertTrue(Thread.currentThread().isInterrupted());
|
||||
} finally {
|
||||
interrupter.cancel(true);
|
||||
Thread.interrupted(); // clear interrupt status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test two threads blocked in timed accept where no connection is established.
|
||||
*/
|
||||
public void testTimedAccept10() throws Exception {
|
||||
ExecutorService pool = Executors.newFixedThreadPool(2);
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(4000);
|
||||
|
||||
long startMillis = millisTime();
|
||||
|
||||
Future<Socket> result1 = pool.submit(ss::accept);
|
||||
Future<Socket> result2 = pool.submit(ss::accept);
|
||||
|
||||
// both tasks should complete with SocketTimeoutException
|
||||
Throwable e = expectThrows(ExecutionException.class, result1::get);
|
||||
assertTrue(e.getCause() instanceof SocketTimeoutException);
|
||||
e = expectThrows(ExecutionException.class, result2::get);
|
||||
assertTrue(e.getCause() instanceof SocketTimeoutException);
|
||||
|
||||
// should get here in 4 seconds, not 8 seconds
|
||||
int timeout = ss.getSoTimeout();
|
||||
checkDuration(startMillis, timeout-100, timeout+2000);
|
||||
} finally {
|
||||
pool.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test two threads blocked in timed accept where one connection is established.
|
||||
*/
|
||||
public void testTimedAccept11() throws Exception {
|
||||
ExecutorService pool = Executors.newFixedThreadPool(2);
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
ss.setSoTimeout(4000);
|
||||
|
||||
long startMillis = millisTime();
|
||||
|
||||
Future<Socket> result1 = pool.submit(ss::accept);
|
||||
Future<Socket> result2 = pool.submit(ss::accept);
|
||||
|
||||
// establish connection after 2 seconds
|
||||
scheduleConnect(ss.getLocalSocketAddress(), 2000);
|
||||
|
||||
// one task should have accepted the connection, the other should
|
||||
// have completed with SocketTimeoutException
|
||||
Socket s1 = null;
|
||||
try {
|
||||
s1 = result1.get();
|
||||
s1.close();
|
||||
} catch (ExecutionException e) {
|
||||
assertTrue(e.getCause() instanceof SocketTimeoutException);
|
||||
}
|
||||
Socket s2 = null;
|
||||
try {
|
||||
s2 = result2.get();
|
||||
s2.close();
|
||||
} catch (ExecutionException e) {
|
||||
assertTrue(e.getCause() instanceof SocketTimeoutException);
|
||||
}
|
||||
assertTrue((s1 != null) ^ (s2 != null));
|
||||
|
||||
// should get here in 4 seconds, not 8 seconds
|
||||
int timeout = ss.getSoTimeout();
|
||||
checkDuration(startMillis, timeout-100, timeout+2000);
|
||||
} finally {
|
||||
pool.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@ -411,6 +525,19 @@ public class Timeouts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a ServerSocket bound to a port on the loopback address
|
||||
*/
|
||||
static ServerSocket boundServerSocket() throws IOException {
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
return ss;
|
||||
}
|
||||
|
||||
/**
|
||||
* An operation that accepts two arguments and may throw IOException
|
||||
*/
|
||||
interface ThrowingBiConsumer<T, U> {
|
||||
void accept(T t, U u) throws IOException;
|
||||
}
|
||||
@ -423,7 +550,7 @@ public class Timeouts {
|
||||
{
|
||||
Socket s1 = null;
|
||||
Socket s2 = null;
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
try (ServerSocket ss = boundServerSocket()) {
|
||||
s1 = new Socket();
|
||||
s1.connect(ss.getLocalSocketAddress());
|
||||
s2 = ss.accept();
|
||||
@ -445,6 +572,13 @@ public class Timeouts {
|
||||
}, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule thread to be interrupted after a delay
|
||||
*/
|
||||
static Future<?> scheduleInterrupt(Thread thread, long delay) {
|
||||
return schedule(() -> thread.interrupt(), delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a thread to connect to the given end point after a delay
|
||||
*/
|
||||
@ -482,12 +616,36 @@ public class Timeouts {
|
||||
scheduleWrite(out, new byte[] { (byte)b }, delay);
|
||||
}
|
||||
|
||||
static void schedule(Runnable task, long delay) {
|
||||
static Future<?> schedule(Runnable task, long delay) {
|
||||
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
try {
|
||||
executor.schedule(task, delay, TimeUnit.MILLISECONDS);
|
||||
return executor.schedule(task, delay, TimeUnit.MILLISECONDS);
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current time in milliseconds.
|
||||
*/
|
||||
private static long millisTime() {
|
||||
long now = System.nanoTime();
|
||||
return TimeUnit.MILLISECONDS.convert(now, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the duration of a task
|
||||
* @param start start time, in milliseconds
|
||||
* @param min minimum expected duration, in milliseconds
|
||||
* @param max maximum expected duration, in milliseconds
|
||||
* @return the duration (now - start), in milliseconds
|
||||
*/
|
||||
private static long checkDuration(long start, long min, long max) {
|
||||
long duration = millisTime() - start;
|
||||
assertTrue(duration >= min,
|
||||
"Duration " + duration + "ms, expected >= " + min + "ms");
|
||||
assertTrue(duration <= max,
|
||||
"Duration " + duration + "ms, expected <= " + max + "ms");
|
||||
return duration;
|
||||
}
|
||||
}
|
||||
|
@ -23,24 +23,36 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @run main UdpSocket
|
||||
* @run testng/othervm -Dsun.net.maxDatagramSockets=32 UdpSocket
|
||||
* @summary Basic test for a Socket to a UDP socket
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.security.Permission;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class UdpSocket {
|
||||
|
||||
static final String MESSAGE = "hello";
|
||||
/**
|
||||
* Test using the Socket API to send/receive datagrams
|
||||
*/
|
||||
public void testSendReceive() throws IOException {
|
||||
final String MESSAGE = "hello";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
try (DatagramChannel dc = DatagramChannel.open()) {
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
dc.bind(new InetSocketAddress(loopback, 0));
|
||||
@ -56,8 +68,7 @@ public class UdpSocket {
|
||||
var buf = ByteBuffer.allocate(100);
|
||||
SocketAddress remote = dc.receive(buf);
|
||||
buf.flip();
|
||||
if (buf.remaining() != MESSAGE.length())
|
||||
throw new RuntimeException("Unexpected size");
|
||||
assertTrue(buf.remaining() == MESSAGE.length(), "Unexpected size");
|
||||
|
||||
// echo the datagram
|
||||
dc.send(buf, remote);
|
||||
@ -65,11 +76,71 @@ public class UdpSocket {
|
||||
// receive datagram with the socket input stream
|
||||
byte[] array2 = new byte[100];
|
||||
int n = s.getInputStream().read(array2);
|
||||
if (n != MESSAGE.length())
|
||||
throw new RuntimeException("Unexpected size");
|
||||
if (!Arrays.equals(array1, 0, n, array2, 0, n))
|
||||
throw new RuntimeException("Unexpected contents");
|
||||
assertTrue(n == MESSAGE.length(), "Unexpected size");
|
||||
assertEquals(Arrays.copyOf(array1, n), Arrays.copyOf(array2, n),
|
||||
"Unexpected contents");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the number of UDP sockets is limited when running with a
|
||||
* security manager.
|
||||
*/
|
||||
public void testMaxSockets() throws Exception {
|
||||
int limit = Integer.getInteger("sun.net.maxDatagramSockets");
|
||||
|
||||
// security manager grants all permissions
|
||||
var securityManager = new SecurityManager() {
|
||||
@Override public void checkPermission(Permission perm) { }
|
||||
};
|
||||
|
||||
System.setSecurityManager(securityManager);
|
||||
Deque<Socket> sockets = new ArrayDeque<>();
|
||||
try {
|
||||
// create the maximum number of sockets
|
||||
for (int i=0; i<limit; i++) {
|
||||
sockets.offer(newUdpSocket());
|
||||
}
|
||||
|
||||
// try to create another socket - should fail
|
||||
try {
|
||||
Socket s = newUdpSocket();
|
||||
s.close();
|
||||
assertTrue(false);
|
||||
} catch (IOException expected) { }
|
||||
|
||||
// close one socket
|
||||
sockets.pop().close();
|
||||
|
||||
// try to create another socket - should succeed
|
||||
Socket s = newUdpSocket();
|
||||
|
||||
// unreference the socket and wait for it to be closed by the cleaner
|
||||
var ref = new WeakReference<>(s);
|
||||
s = null;
|
||||
while (ref.get() != null) {
|
||||
System.gc();
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
// try to create another socket - should succeed
|
||||
s = newUdpSocket();
|
||||
s.close();
|
||||
} finally {
|
||||
closeAll(sockets);
|
||||
System.setSecurityManager(null);
|
||||
}
|
||||
}
|
||||
|
||||
private Socket newUdpSocket() throws IOException {
|
||||
return new Socket(InetAddress.getLoopbackAddress(), 8000, false);
|
||||
}
|
||||
|
||||
private void closeAll(Deque<Socket> sockets) throws IOException {
|
||||
Socket s;
|
||||
while ((s = sockets.poll()) != null) {
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,6 +35,7 @@ import static java.util.concurrent.CompletableFuture.*;
|
||||
* cause any thread blocked on the socket to throw a SocketException.
|
||||
* @run main AsyncClose
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true AsyncClose
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl AsyncClose
|
||||
*/
|
||||
|
||||
public class AsyncClose {
|
||||
|
490
test/jdk/java/net/SocketImpl/BadUsages.java
Normal file
490
test/jdk/java/net/SocketImpl/BadUsages.java
Normal file
@ -0,0 +1,490 @@
|
||||
/*
|
||||
* 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 8221481
|
||||
* @compile/module=java.base java/net/PlatformSocketImpl.java
|
||||
* @run testng/othervm BadUsages
|
||||
* @summary Test the platform SocketImpl when used in unintended ways
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketImpl;
|
||||
import java.net.SocketOption;
|
||||
import java.net.SocketOptions;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.util.Set;
|
||||
|
||||
import java.net.PlatformSocketImpl; // test helper
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/**
|
||||
* SocketImpl does not specify how the SocketImpl behaves when used in ways
|
||||
* that are not intended, e.g. invoking socket operations before the socket is
|
||||
* created or trying to establish a connection after the socket is connected or
|
||||
* closed.
|
||||
*
|
||||
* This test exercises the platform SocketImpl to test that it is reliable, and
|
||||
* throws reasonable exceptions, for these scenarios.
|
||||
*/
|
||||
|
||||
@Test
|
||||
public class BadUsages {
|
||||
|
||||
/**
|
||||
* Test create when already created.
|
||||
*/
|
||||
public void testCreate1() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
expectThrows(IOException.class, () -> impl.create(true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test create when closed.
|
||||
*/
|
||||
public void testCreate2() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
expectThrows(IOException.class, () -> impl.create(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test connect when not created.
|
||||
*/
|
||||
public void testConnect1() throws IOException {
|
||||
try (var ss = new ServerSocket(0)) {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
var address = ss.getInetAddress();
|
||||
int port = ss.getLocalPort();
|
||||
expectThrows(IOException.class, () -> impl.connect(address, port));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test connect with unsupported address type.
|
||||
*/
|
||||
public void testConnect2() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
var remote = new SocketAddress() { };
|
||||
expectThrows(IOException.class, () -> impl.connect(remote, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test connect with an unresolved address.
|
||||
*/
|
||||
public void testConnect3() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
var remote = new InetSocketAddress("blah-blah.blah-blah", 80);
|
||||
expectThrows(IOException.class, () -> impl.connect(remote, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test connect when already connected.
|
||||
*/
|
||||
public void testConnect4() throws IOException {
|
||||
try (var ss = new ServerSocket();
|
||||
var impl = new PlatformSocketImpl(false)) {
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
impl.create(true);
|
||||
int port = ss.getLocalPort();
|
||||
impl.connect(loopback, port);
|
||||
expectThrows(IOException.class, () -> impl.connect(loopback, port));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test connect when closed.
|
||||
*/
|
||||
public void testConnect5() throws IOException {
|
||||
try (var ss = new ServerSocket(0)) {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
String host = ss.getInetAddress().getHostAddress();
|
||||
int port = ss.getLocalPort();
|
||||
expectThrows(IOException.class, () -> impl.connect(host, port));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test bind when not created.
|
||||
*/
|
||||
public void testBind1() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
expectThrows(IOException.class, () -> impl.bind(loopback, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test bind when already bound.
|
||||
*/
|
||||
public void testBind2() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
impl.bind(loopback, 0);
|
||||
expectThrows(IOException.class, () -> impl.bind(loopback, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test bind when connected.
|
||||
*/
|
||||
public void testBind3() throws IOException {
|
||||
try (var ss = new ServerSocket();
|
||||
var impl = new PlatformSocketImpl(false)) {
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
impl.create(true);
|
||||
impl.connect(ss.getLocalSocketAddress(), 0);
|
||||
expectThrows(IOException.class, () -> impl.bind(loopback, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test bind when closed.
|
||||
*/
|
||||
public void testBind4() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
expectThrows(IOException.class, () -> impl.bind(loopback, 0));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test listen when not created.
|
||||
*/
|
||||
public void testListen1() {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class, () -> impl.listen(16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test listen when not bound.
|
||||
*/
|
||||
public void testListen2() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
expectThrows(IOException.class, () -> impl.listen(16));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test listen when closed.
|
||||
*/
|
||||
public void testListen3() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
expectThrows(IOException.class, () -> impl.listen(16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test accept when not created.
|
||||
*/
|
||||
public void testAccept1() throws IOException {
|
||||
var impl = new PlatformSocketImpl(true);
|
||||
var si = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class, () -> impl.accept(si));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test accept when not bound.
|
||||
*/
|
||||
public void testAccept2() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(true)) {
|
||||
impl.create(true);
|
||||
var si = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class, () -> impl.accept(si));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test accept when not a stream socket.
|
||||
*/
|
||||
public void testAccept3() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(false);
|
||||
impl.bind(InetAddress.getLoopbackAddress(), 0);
|
||||
var si = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class, () -> impl.accept(si));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test accept when closed.
|
||||
*/
|
||||
public void testAccept4() throws IOException {
|
||||
var impl = new PlatformSocketImpl(true);
|
||||
impl.close();
|
||||
var si = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class, () -> impl.accept(si));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test accept with SocketImpl that is already created.
|
||||
*/
|
||||
public void testAccept5() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(true);
|
||||
var si = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
impl.bind(InetAddress.getLoopbackAddress(), 0);
|
||||
si.create(true);
|
||||
expectThrows(IOException.class, () -> impl.accept(si));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test accept with SocketImpl that is closed.
|
||||
*/
|
||||
public void testAccept6() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(true);
|
||||
var si = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
impl.bind(InetAddress.getLoopbackAddress(), 0);
|
||||
si.create(true);
|
||||
si.close();
|
||||
expectThrows(IOException.class, () -> impl.accept(si));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test available when not created.
|
||||
*/
|
||||
public void testAvailable1() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class, () -> impl.available());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test available when created but not connected.
|
||||
*/
|
||||
public void testAvailable2() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
expectThrows(IOException.class, () -> impl.available());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test available when closed.
|
||||
*/
|
||||
public void testAvailable3() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
expectThrows(IOException.class, () -> impl.available());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setOption when not created.
|
||||
*/
|
||||
public void testSetOption1() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class,
|
||||
() -> impl.setOption(StandardSocketOptions.SO_REUSEADDR, true));
|
||||
// legacy
|
||||
expectThrows(SocketException.class,
|
||||
() -> impl.setOption(SocketOptions.SO_REUSEADDR, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setOption when closed.
|
||||
*/
|
||||
public void testSetOption2() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
expectThrows(IOException.class,
|
||||
() -> impl.setOption(StandardSocketOptions.SO_REUSEADDR, true));
|
||||
// legacy
|
||||
expectThrows(SocketException.class,
|
||||
() -> impl.setOption(SocketOptions.SO_REUSEADDR, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setOption with unsupported option.
|
||||
*/
|
||||
public void testSetOption3() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
var opt = new SocketOption<String>() {
|
||||
@Override public String name() { return "birthday"; }
|
||||
@Override public Class<String> type() { return String.class; }
|
||||
};
|
||||
expectThrows(UnsupportedOperationException.class, () -> impl.setOption(opt, ""));
|
||||
// legacy
|
||||
expectThrows(SocketException.class, () -> impl.setOption(-1, ""));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setOption(int, Object) with invalid values.
|
||||
*/
|
||||
public void testSetOption4() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
expectThrows(SocketException.class,
|
||||
() -> impl.setOption(SocketOptions.SO_REUSEADDR, -1));
|
||||
expectThrows(SocketException.class,
|
||||
() -> impl.setOption(SocketOptions.SO_TIMEOUT, -1));
|
||||
expectThrows(SocketException.class,
|
||||
() -> impl.setOption(SocketOptions.SO_SNDBUF, -1));
|
||||
expectThrows(SocketException.class,
|
||||
() -> impl.setOption(SocketOptions.SO_RCVBUF, -1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getOption when not created.
|
||||
*/
|
||||
public void testGetOption1() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class,
|
||||
() -> impl.getOption(StandardSocketOptions.SO_REUSEADDR));
|
||||
expectThrows(SocketException.class,
|
||||
() -> impl.getOption(-1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getOption when closed.
|
||||
*/
|
||||
public void testGetOption2() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
expectThrows(IOException.class,
|
||||
() -> impl.getOption(StandardSocketOptions.SO_REUSEADDR));
|
||||
expectThrows(SocketException.class,
|
||||
() -> impl.getOption(SocketOptions.SO_REUSEADDR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getOption with unsupported option.
|
||||
*/
|
||||
public void testGetOption3() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
var opt = new SocketOption<String>() {
|
||||
@Override public String name() { return "birthday"; }
|
||||
@Override public Class<String> type() { return String.class; }
|
||||
};
|
||||
expectThrows(UnsupportedOperationException.class, () -> impl.getOption(opt));
|
||||
expectThrows(SocketException.class, () -> impl.getOption(-1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test shutdownInput when not created.
|
||||
*/
|
||||
public void testShutdownInput1() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class, () -> impl.shutdownInput());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test shutdownInput when not connected.
|
||||
*/
|
||||
public void testShutdownInput2() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
expectThrows(IOException.class, () -> impl.shutdownInput());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test shutdownInput when closed.
|
||||
*/
|
||||
public void testShutdownInput3() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
expectThrows(IOException.class, () -> impl.shutdownInput());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test shutdownOutput when not created.
|
||||
*/
|
||||
public void testShutdownOutput1() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class, () -> impl.shutdownOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test shutdownOutput when not connected.
|
||||
*/
|
||||
public void testShutdownOutput2() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
expectThrows(IOException.class, () -> impl.shutdownOutput());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test shutdownOutput when closed.
|
||||
*/
|
||||
public void testShutdownOutput3() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
expectThrows(IOException.class, () -> impl.shutdownOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sendUrgentData when not created.
|
||||
*/
|
||||
public void testSendUrgentData1() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
expectThrows(IOException.class, () -> impl.sendUrgentData(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sendUrgentData when not connected.
|
||||
*/
|
||||
public void testSendUrgentData2() throws IOException {
|
||||
try (var impl = new PlatformSocketImpl(false)) {
|
||||
impl.create(true);
|
||||
expectThrows(IOException.class, () -> impl.sendUrgentData(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sendUrgentData when closed.
|
||||
*/
|
||||
public void testSendUrgentData3() throws IOException {
|
||||
var impl = new PlatformSocketImpl(false);
|
||||
impl.close();
|
||||
expectThrows(IOException.class, () -> impl.sendUrgentData(0));
|
||||
}
|
||||
}
|
81
test/jdk/java/net/SocketImpl/CompareSocketOptions.java
Normal file
81
test/jdk/java/net/SocketImpl/CompareSocketOptions.java
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 8221481
|
||||
* @modules java.base/java.net:+open java.base/sun.nio.ch:+open
|
||||
* @run testng CompareSocketOptions
|
||||
* @summary Compare the set of socket options supported by the old and new SocketImpls
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketImpl;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class CompareSocketOptions {
|
||||
|
||||
/**
|
||||
* Test that the old and new platform SocketImpl support the same set of
|
||||
* client socket options.
|
||||
*/
|
||||
public void testClientSocketSupportedOptions() throws IOException {
|
||||
Socket s1 = new Socket(createOldSocketImpl(false)) { };
|
||||
Socket s2 = new Socket(createNewSocketImpl(false)) { };
|
||||
assertEquals(s1.supportedOptions(), s2.supportedOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the old and new platform SocketImpl support the same set of
|
||||
* server socket options.
|
||||
*/
|
||||
public void testServerSocketSupportedOptions() throws IOException {
|
||||
ServerSocket ss1 = new ServerSocket(createOldSocketImpl(true)) { };
|
||||
ServerSocket ss2 = new ServerSocket(createNewSocketImpl(true)) { };
|
||||
assertEquals(ss1.supportedOptions(), ss2.supportedOptions());
|
||||
}
|
||||
|
||||
private static SocketImpl createOldSocketImpl(boolean server) {
|
||||
return newPlatformSocketImpl("java.net.PlainSocketImpl", server);
|
||||
}
|
||||
|
||||
private static SocketImpl createNewSocketImpl(boolean server) {
|
||||
return newPlatformSocketImpl("sun.nio.ch.NioSocketImpl", server);
|
||||
}
|
||||
|
||||
private static SocketImpl newPlatformSocketImpl(String name, boolean server) {
|
||||
try {
|
||||
var ctor = Class.forName(name).getDeclaredConstructor(boolean.class);
|
||||
ctor.setAccessible(true);
|
||||
return (SocketImpl) ctor.newInstance(server);
|
||||
} catch (Exception e) {
|
||||
fail("Should not get here", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A SocketImpl that delegates all operations to a platform SocketImpl. It also
|
||||
* overrides all methods with public methods and implements AutoCloseable to make
|
||||
* it easy to write tests.
|
||||
*/
|
||||
|
||||
public class PlatformSocketImpl extends SocketImpl implements AutoCloseable {
|
||||
private final SocketImpl impl;
|
||||
|
||||
public PlatformSocketImpl(boolean server) {
|
||||
impl = new sun.nio.ch.NioSocketImpl(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
impl.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(boolean stream) throws IOException {
|
||||
impl.create(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(SocketAddress remote, int millis) throws IOException {
|
||||
impl.connect(remote, millis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(String host, int port) throws IOException {
|
||||
impl.connect(host, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(InetAddress address, int port) throws IOException {
|
||||
impl.connect(address, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(InetAddress address, int port) throws IOException {
|
||||
impl.bind(address, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listen(int backlog) throws IOException {
|
||||
impl.listen(backlog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SocketImpl si) throws IOException {
|
||||
impl.accept(((PlatformSocketImpl) si).impl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return impl.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
return impl.getOutputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return impl.available();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketOption<?>> supportedOptions() {
|
||||
return impl.supportedOptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setOption(SocketOption<T> opt, T value) throws IOException {
|
||||
impl.setOption(opt, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getOption(SocketOption<T> opt) throws IOException {
|
||||
return impl.getOption(opt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOption(int opt, Object value) throws SocketException {
|
||||
impl.setOption(opt, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOption(int opt) throws SocketException {
|
||||
return impl.getOption(opt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdownInput() throws IOException {
|
||||
impl.shutdownInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdownOutput() throws IOException {
|
||||
impl.shutdownOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUrgentData() {
|
||||
return impl.supportsUrgentData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendUrgentData(int data) throws IOException {
|
||||
impl.sendUrgentData(data);
|
||||
}
|
||||
}
|
@ -38,23 +38,24 @@ import jdk.test.lib.net.IPSupport;
|
||||
|
||||
public class OptionsTest {
|
||||
|
||||
static class Test {
|
||||
Test(SocketOption<?> option, Object testValue) {
|
||||
static class Test<T> {
|
||||
final SocketOption<T> option;
|
||||
final T value;
|
||||
Test(SocketOption<T> option, T value) {
|
||||
this.option = option;
|
||||
this.testValue = testValue;
|
||||
this.value = value;
|
||||
}
|
||||
static Test create (SocketOption<?> option, Object testValue) {
|
||||
return new Test(option, testValue);
|
||||
static <T> Test<T> create(SocketOption<T> option, T value) {
|
||||
return new Test<T>(option, value);
|
||||
}
|
||||
Object option;
|
||||
Object testValue;
|
||||
|
||||
}
|
||||
|
||||
// The tests set the option using the new API, read back the set value
|
||||
// which could be diferent, and then use the legacy get API to check
|
||||
// these values are the same
|
||||
|
||||
static Test[] socketTests = new Test[] {
|
||||
static Test<?>[] socketTests = new Test<?>[] {
|
||||
Test.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE),
|
||||
Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
|
||||
@ -66,7 +67,7 @@ public class OptionsTest {
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound
|
||||
};
|
||||
|
||||
static Test[] serverSocketTests = new Test[] {
|
||||
static Test<?>[] serverSocketTests = new Test<?>[] {
|
||||
Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
|
||||
@ -75,7 +76,7 @@ public class OptionsTest {
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound
|
||||
};
|
||||
|
||||
static Test[] dgSocketTests = new Test[] {
|
||||
static Test<?>[] datagramSocketTests = new Test<?>[] {
|
||||
Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
|
||||
@ -85,7 +86,7 @@ public class OptionsTest {
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound
|
||||
};
|
||||
|
||||
static Test[] mcSocketTests = new Test[] {
|
||||
static Test<?>[] multicastSocketTests = new Test<?>[] {
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()),
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(0)), // lower-bound
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)),
|
||||
@ -97,7 +98,7 @@ public class OptionsTest {
|
||||
try {
|
||||
Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
|
||||
while (nifs.hasMoreElements()) {
|
||||
NetworkInterface ni = (NetworkInterface)nifs.nextElement();
|
||||
NetworkInterface ni = nifs.nextElement();
|
||||
if (ni.supportsMulticast()) {
|
||||
return ni;
|
||||
}
|
||||
@ -107,99 +108,110 @@ public class OptionsTest {
|
||||
return null;
|
||||
}
|
||||
|
||||
static boolean okayToTest(Socket s, SocketOption<?> option) {
|
||||
if (option == StandardSocketOptions.SO_REUSEPORT) {
|
||||
// skip SO_REUSEPORT if option is not supported
|
||||
return s.supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
}
|
||||
if (option == StandardSocketOptions.IP_TOS && s.isConnected()) {
|
||||
// skip IP_TOS if connected
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static <T> void testEqual(SocketOption<T> option, T value1, T value2) {
|
||||
if (!value1.equals(value2)) {
|
||||
throw new RuntimeException("Test of " + option.name() + " failed: "
|
||||
+ value1 + " != " + value2);
|
||||
}
|
||||
}
|
||||
|
||||
static <T> void test(Socket s, Test<T> test) throws Exception {
|
||||
SocketOption<T> option = test.option;
|
||||
s.setOption(option, test.value);
|
||||
T value1 = s.getOption(test.option);
|
||||
T value2 = (T) legacyGetOption(Socket.class, s, test.option);
|
||||
testEqual(option, value1, value2);
|
||||
}
|
||||
|
||||
static <T> void test(ServerSocket ss, Test<T> test) throws Exception {
|
||||
SocketOption<T> option = test.option;
|
||||
ss.setOption(option, test.value);
|
||||
T value1 = ss.getOption(test.option);
|
||||
T value2 = (T) legacyGetOption(ServerSocket.class, ss, test.option);
|
||||
testEqual(option, value1, value2);
|
||||
}
|
||||
|
||||
static <T> void test(DatagramSocket ds, Test<T> test) throws Exception {
|
||||
SocketOption<T> option = test.option;
|
||||
ds.setOption(option, test.value);
|
||||
T value1 = ds.getOption(test.option);
|
||||
T value2 = (T) legacyGetOption(ds.getClass(), ds, test.option);
|
||||
testEqual(option, value1, value2);
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
static void doSocketTests() throws Exception {
|
||||
try (
|
||||
ServerSocket srv = new ServerSocket(0, 50, InetAddress.getLoopbackAddress());
|
||||
Socket c = new Socket(InetAddress.getLoopbackAddress(), srv.getLocalPort());
|
||||
Socket s = srv.accept();
|
||||
) {
|
||||
Set<SocketOption<?>> options = c.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
for (int i=0; i<socketTests.length; i++) {
|
||||
Test test = socketTests[i];
|
||||
if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
|
||||
c.setOption((SocketOption)test.option, test.testValue);
|
||||
Object getval = c.getOption((SocketOption)test.option);
|
||||
Object legacyget = legacyGetOption(Socket.class, c,test.option);
|
||||
if (!getval.equals(legacyget)) {
|
||||
Formatter f = new Formatter();
|
||||
f.format("S Err %d: %s/%s", i, getval, legacyget);
|
||||
throw new RuntimeException(f.toString());
|
||||
}
|
||||
// unconnected socket
|
||||
try (Socket s = new Socket()) {
|
||||
for (Test<?> test : socketTests) {
|
||||
if (okayToTest(s, test.option)) {
|
||||
test(s, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doDgSocketTests() throws Exception {
|
||||
try (
|
||||
DatagramSocket c = new DatagramSocket(0);
|
||||
) {
|
||||
Set<SocketOption<?>> options = c.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
for (int i=0; i<dgSocketTests.length; i++) {
|
||||
Test test = dgSocketTests[i];
|
||||
if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
|
||||
c.setOption((SocketOption)test.option, test.testValue);
|
||||
Object getval = c.getOption((SocketOption)test.option);
|
||||
Object legacyget = legacyGetOption(DatagramSocket.class, c,test.option);
|
||||
if (!getval.equals(legacyget)) {
|
||||
Formatter f = new Formatter();
|
||||
f.format("DG Err %d: %s/%s", i, getval, legacyget);
|
||||
throw new RuntimeException(f.toString());
|
||||
// connected socket
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
try (Socket s1 = new Socket()) {
|
||||
s1.connect(ss.getLocalSocketAddress());
|
||||
try (Socket s2 = ss.accept()) {
|
||||
for (Test<?> test : socketTests) {
|
||||
if (okayToTest(s1, test.option)) {
|
||||
test(s1, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doMcSocketTests() throws Exception {
|
||||
try (
|
||||
MulticastSocket c = new MulticastSocket(0);
|
||||
) {
|
||||
for (int i=0; i<mcSocketTests.length; i++) {
|
||||
Test test = mcSocketTests[i];
|
||||
c.setOption((SocketOption)test.option, test.testValue);
|
||||
Object getval = c.getOption((SocketOption)test.option);
|
||||
Object legacyget = legacyGetOption(MulticastSocket.class, c,test.option);
|
||||
if (!getval.equals(legacyget)) {
|
||||
Formatter f = new Formatter();
|
||||
f.format("MC Err %d: %s/%s", i, getval, legacyget);
|
||||
throw new RuntimeException(f.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doServerSocketTests() throws Exception {
|
||||
try (
|
||||
ServerSocket c = new ServerSocket(0);
|
||||
) {
|
||||
Set<SocketOption<?>> options = c.supportedOptions();
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
Set<SocketOption<?>> options = ss.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
for (int i=0; i<serverSocketTests.length; i++) {
|
||||
Test test = serverSocketTests[i];
|
||||
for (Test<?> test : serverSocketTests) {
|
||||
if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
|
||||
c.setOption((SocketOption)test.option, test.testValue);
|
||||
Object getval = c.getOption((SocketOption)test.option);
|
||||
Object legacyget = legacyGetOption(
|
||||
ServerSocket.class, c, test.option
|
||||
);
|
||||
if (!getval.equals(legacyget)) {
|
||||
Formatter f = new Formatter();
|
||||
f.format("SS Err %d: %s/%s", i, getval, legacyget);
|
||||
throw new RuntimeException(f.toString());
|
||||
}
|
||||
test(ss, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Object legacyGetOption(
|
||||
Class<?> type, Object s, Object option)
|
||||
static void doDatagramSocketTests() throws Exception {
|
||||
try (DatagramSocket ds = new DatagramSocket(0)) {
|
||||
Set<SocketOption<?>> options = ds.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
for (Test<?> test : datagramSocketTests) {
|
||||
if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
|
||||
test(ds, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throws Exception
|
||||
{
|
||||
static void doMulticastSocketTests() throws Exception {
|
||||
try (MulticastSocket ms = new MulticastSocket(0)) {
|
||||
for (Test<?> test : multicastSocketTests) {
|
||||
test(ms, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Object legacyGetOption(Class<?> type, Object s, Object option) throws Exception {
|
||||
if (type.equals(Socket.class)) {
|
||||
Socket socket = (Socket)s;
|
||||
Set<SocketOption<?>> options = socket.supportedOptions();
|
||||
@ -291,8 +303,8 @@ public class OptionsTest {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
doSocketTests();
|
||||
doServerSocketTests();
|
||||
doDgSocketTests();
|
||||
doMcSocketTests();
|
||||
doDatagramSocketTests();
|
||||
doMulticastSocketTests();
|
||||
}
|
||||
|
||||
// Reflectively access jdk.net.Sockets.getOption so that the test can run
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -32,6 +32,7 @@
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* @run main TcpTest -d
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl TcpTest -d
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -197,14 +197,19 @@ public class NewSocketMethods {
|
||||
/**
|
||||
* test some new methods of java.net.Socket added to merlin.
|
||||
*/
|
||||
socket.setTrafficClass(8);
|
||||
socket.setReuseAddress(true);
|
||||
System.out.println("Client getTrafficClass(): "
|
||||
+ socket.getTrafficClass());
|
||||
System.out.println("Client isInputShutdown() "
|
||||
+ socket.isInputShutdown());
|
||||
socket.setReuseAddress(true);
|
||||
System.out.println("Client getReuseAddress(): "
|
||||
+ socket.getReuseAddress());
|
||||
|
||||
// Solaris does not support set/get of IPV6_TCLASS when connected
|
||||
if (!"SunOS".equals(System.getProperty("os.name"))) {
|
||||
socket.setTrafficClass(8);
|
||||
System.out.println("Client getTrafficClass(): "
|
||||
+ socket.getTrafficClass());
|
||||
}
|
||||
|
||||
os.write(237);
|
||||
os.flush();
|
||||
System.out.println("Client read: " + is.read());
|
||||
|
Loading…
Reference in New Issue
Block a user