undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
207
test/jdk/java/nio/channels/SocketChannel/AdaptSocket.java
Normal file
207
test/jdk/java/nio/channels/SocketChannel/AdaptSocket.java
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 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 8156002 8201474
|
||||
* @summary Unit test for socket-channel adaptors
|
||||
* @library .. /test/lib
|
||||
* @build jdk.test.lib.Utils TestServers
|
||||
* @run main AdaptSocket
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
public class AdaptSocket {
|
||||
|
||||
static final java.io.PrintStream out = System.out;
|
||||
|
||||
static void test(TestServers.AbstractServer server,
|
||||
int timeout,
|
||||
boolean shouldTimeout)
|
||||
throws Exception
|
||||
{
|
||||
out.println();
|
||||
|
||||
InetSocketAddress isa = new InetSocketAddress(server.getAddress(), server.getPort());
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
Socket so = sc.socket();
|
||||
out.println("opened: " + so);
|
||||
out.println(" " + sc);
|
||||
|
||||
//out.println("opts: " + sc.options());
|
||||
so.setTcpNoDelay(true);
|
||||
//so.setTrafficClass(SocketOpts.IP.TOS_THROUGHPUT);
|
||||
so.setKeepAlive(true);
|
||||
so.setSoLinger(true, 42);
|
||||
so.setOOBInline(true);
|
||||
so.setReceiveBufferSize(512);
|
||||
so.setSendBufferSize(512);
|
||||
//out.println(" " + sc.options());
|
||||
|
||||
if (timeout == 0)
|
||||
so.connect(isa);
|
||||
else {
|
||||
try {
|
||||
so.connect(isa, timeout);
|
||||
} catch (SocketTimeoutException x) {
|
||||
if (shouldTimeout) {
|
||||
out.println("Connection timed out, as expected");
|
||||
return;
|
||||
} else {
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
}
|
||||
out.println("connected: " + so);
|
||||
out.println(" " + sc);
|
||||
byte[] bb = new byte[100];
|
||||
int n = so.getInputStream().read(bb);
|
||||
String s = new String(bb, 0, n - 2, "US-ASCII");
|
||||
out.println(isa + " says: \"" + s + "\"");
|
||||
so.shutdownInput();
|
||||
out.println("ishut: " + sc);
|
||||
so.shutdownOutput();
|
||||
out.println("oshut: " + sc);
|
||||
so.close();
|
||||
out.println("closed: " + so);
|
||||
out.println(" " + sc);
|
||||
}
|
||||
|
||||
static String dataString = "foo\r\n";
|
||||
|
||||
static void testRead(Socket so, boolean shouldTimeout)
|
||||
throws Exception
|
||||
{
|
||||
String data = "foo\r\n";
|
||||
so.getOutputStream().write(dataString.getBytes("US-ASCII"));
|
||||
InputStream is = so.getInputStream();
|
||||
try {
|
||||
byte[] b = new byte[100];
|
||||
int n = is.read(b);
|
||||
if (shouldTimeout) {
|
||||
throw new Exception("Should time out, but not, data: " + Arrays.toString(b));
|
||||
}
|
||||
if (n != 5) {
|
||||
throw new Exception("Incorrect number of bytes read: " + n);
|
||||
}
|
||||
if (!dataString.equals(new String(b, 0, n, "US-ASCII"))) {
|
||||
throw new Exception("Incorrect data read: " + n);
|
||||
}
|
||||
} catch (SocketTimeoutException x) {
|
||||
if (shouldTimeout) {
|
||||
out.println("Read timed out, as expected");
|
||||
return;
|
||||
}
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
|
||||
static void testRead(TestServers.EchoServer echoServer,
|
||||
int timeout,
|
||||
boolean shouldTimeout)
|
||||
throws Exception
|
||||
{
|
||||
out.println();
|
||||
|
||||
InetSocketAddress isa
|
||||
= new InetSocketAddress(echoServer.getAddress(),
|
||||
echoServer.getPort());
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
sc.connect(isa);
|
||||
Socket so = sc.socket();
|
||||
out.println("connected: " + so);
|
||||
out.println(" " + sc);
|
||||
|
||||
if (timeout > 0)
|
||||
so.setSoTimeout(timeout);
|
||||
out.println("timeout: " + so.getSoTimeout());
|
||||
|
||||
testRead(so, shouldTimeout);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
out.println("loop: " + i);
|
||||
testRead(so, shouldTimeout);
|
||||
}
|
||||
|
||||
sc.close();
|
||||
}
|
||||
|
||||
static void testConnect(TestServers.AbstractServer server,
|
||||
int timeout,
|
||||
boolean shouldFail)
|
||||
throws Exception
|
||||
{
|
||||
SocketAddress sa = new InetSocketAddress(server.getAddress(), server.getPort());
|
||||
try (SocketChannel sc = SocketChannel.open()) {
|
||||
Socket s = sc.socket();
|
||||
try {
|
||||
if (timeout > 0) {
|
||||
s.connect(sa, timeout);
|
||||
} else {
|
||||
s.connect(sa);
|
||||
}
|
||||
if (shouldFail)
|
||||
throw new Exception("Connection should not be established");
|
||||
} catch (SocketException se) {
|
||||
if (!shouldFail)
|
||||
throw se;
|
||||
out.println("connect failed as expected: " + se);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
try (TestServers.DayTimeServer dayTimeServer
|
||||
= TestServers.DayTimeServer.startNewServer()) {
|
||||
test(dayTimeServer, 0, false);
|
||||
test(dayTimeServer, 1000, false);
|
||||
}
|
||||
|
||||
try (TestServers.DayTimeServer lingerDayTimeServer
|
||||
= TestServers.DayTimeServer.startNewServer(100)) {
|
||||
// this test no longer really test the connection timeout
|
||||
// since there is no way to prevent the server from eagerly
|
||||
// accepting connection...
|
||||
test(lingerDayTimeServer, 10, true);
|
||||
}
|
||||
|
||||
try (TestServers.EchoServer echoServer
|
||||
= TestServers.EchoServer.startNewServer()) {
|
||||
testRead(echoServer, 0, false);
|
||||
testRead(echoServer, 8000, false);
|
||||
}
|
||||
|
||||
try (TestServers.NoResponseServer noResponseServer
|
||||
= TestServers.NoResponseServer.startNewServer()) {
|
||||
testRead(noResponseServer, 10, true);
|
||||
}
|
||||
|
||||
TestServers.RefusingServer refuser = TestServers.RefusingServer.newRefusingServer();
|
||||
testConnect(refuser, 0, true);
|
||||
testConnect(refuser, 10000, true);
|
||||
}
|
||||
}
|
||||
522
test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java
Normal file
522
test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java
Normal file
|
|
@ -0,0 +1,522 @@
|
|||
/*
|
||||
* 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 8222774 4430139
|
||||
* @run testng AdaptorStreams
|
||||
* @summary Exercise socket adaptor input/output streams
|
||||
*/
|
||||
|
||||
import java.io.Closeable;
|
||||
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.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.channels.IllegalBlockingModeException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class AdaptorStreams {
|
||||
|
||||
/**
|
||||
* Test read when bytes are available
|
||||
*/
|
||||
public void testRead1() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
peer.getOutputStream().write(99);
|
||||
int n = sc.socket().getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read blocking before bytes are available
|
||||
*/
|
||||
public void testRead2() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
scheduleWrite(peer.getOutputStream(), 99, 1000);
|
||||
int n = sc.socket().getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read when peer has closed connection
|
||||
*/
|
||||
public void testRead3() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
peer.close();
|
||||
int n = sc.socket().getInputStream().read();
|
||||
assertEquals(n, -1);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read blocking before peer closes connection
|
||||
*/
|
||||
public void testRead4() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
scheduleClose(peer, 1000);
|
||||
int n = sc.socket().getInputStream().read();
|
||||
assertEquals(n, -1);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test async close of socket when thread blocked in read
|
||||
*/
|
||||
public void testRead5() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
scheduleClose(sc, 2000);
|
||||
InputStream in = sc.socket().getInputStream();
|
||||
expectThrows(IOException.class, () -> in.read());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test interrupted status set before read
|
||||
*/
|
||||
public void testRead6() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
Thread.currentThread().interrupt();
|
||||
try {
|
||||
InputStream in = s.getInputStream();
|
||||
expectThrows(IOException.class, () -> in.read());
|
||||
} finally {
|
||||
Thread.interrupted(); // clear interrupt
|
||||
}
|
||||
assertTrue(s.isClosed());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test interrupt of thread blocked in read
|
||||
*/
|
||||
public void testRead7() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Future<?> interrupter = scheduleInterrupt(Thread.currentThread(), 2000);
|
||||
Socket s = sc.socket();
|
||||
try {
|
||||
InputStream in = s.getInputStream();
|
||||
expectThrows(IOException.class, () -> in.read());
|
||||
} finally {
|
||||
interrupter.cancel(true);
|
||||
Thread.interrupted(); // clear interrupt
|
||||
}
|
||||
assertTrue(s.isClosed());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read when channel is configured non-blocking
|
||||
*/
|
||||
public void testRead8() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
sc.configureBlocking(false);
|
||||
InputStream in = sc.socket().getInputStream();
|
||||
expectThrows(IllegalBlockingModeException.class, () -> in.read());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test timed read when bytes are available
|
||||
*/
|
||||
public void testTimedRead1() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
peer.getOutputStream().write(99);
|
||||
Socket s = sc.socket();
|
||||
s.setSoTimeout(60_000);
|
||||
int n = s.getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test timed read blocking before bytes are available
|
||||
*/
|
||||
public void testTimedRead2() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
scheduleWrite(peer.getOutputStream(), 99, 1000);
|
||||
Socket s = sc.socket();
|
||||
s.setSoTimeout(60_000);
|
||||
int n = s.getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test timed read when the read times out
|
||||
*/
|
||||
public void testTimedRead3() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
s.setSoTimeout(500);
|
||||
InputStream in = s.getInputStream();
|
||||
expectThrows(SocketTimeoutException.class, () -> in.read());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test async close of socket when thread blocked in timed read
|
||||
*/
|
||||
public void testTimedRead4() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
scheduleClose(sc, 2000);
|
||||
Socket s = sc.socket();
|
||||
s.setSoTimeout(60_000);
|
||||
InputStream in = s.getInputStream();
|
||||
expectThrows(IOException.class, () -> in.read());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test interrupted status set before timed read
|
||||
*/
|
||||
public void testTimedRead5() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
Thread.currentThread().interrupt();
|
||||
try {
|
||||
s.setSoTimeout(60_000);
|
||||
InputStream in = s.getInputStream();
|
||||
expectThrows(IOException.class, () -> in.read());
|
||||
} finally {
|
||||
Thread.interrupted(); // clear interrupt
|
||||
}
|
||||
assertTrue(s.isClosed());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test interrupt of thread blocked in timed read
|
||||
*/
|
||||
public void testTimedRead6() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Future<?> interrupter = scheduleInterrupt(Thread.currentThread(), 2000);
|
||||
Socket s = sc.socket();
|
||||
try {
|
||||
s.setSoTimeout(60_000);
|
||||
InputStream in = s.getInputStream();
|
||||
expectThrows(IOException.class, () -> in.read());
|
||||
assertTrue(s.isClosed());
|
||||
} finally {
|
||||
interrupter.cancel(true);
|
||||
Thread.interrupted(); // clear interrupt
|
||||
}
|
||||
assertTrue(s.isClosed());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test async close of socket when thread blocked in write
|
||||
*/
|
||||
public void testWrite1() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
scheduleClose(sc, 2000);
|
||||
expectThrows(IOException.class, () -> {
|
||||
OutputStream out = sc.socket().getOutputStream();
|
||||
byte[] data = new byte[64*1000];
|
||||
while (true) {
|
||||
out.write(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test interrupted status set before write
|
||||
*/
|
||||
public void testWrite2() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
Thread.currentThread().interrupt();
|
||||
try {
|
||||
OutputStream out = s.getOutputStream();
|
||||
expectThrows(IOException.class, () -> out.write(99));
|
||||
} finally {
|
||||
Thread.interrupted(); // clear interrupt
|
||||
}
|
||||
assertTrue(s.isClosed());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test interrupt of thread blocked in write
|
||||
*/
|
||||
public void testWrite3() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Future<?> interrupter = scheduleInterrupt(Thread.currentThread(), 2000);
|
||||
Socket s = sc.socket();
|
||||
try {
|
||||
expectThrows(IOException.class, () -> {
|
||||
OutputStream out = sc.socket().getOutputStream();
|
||||
byte[] data = new byte[64*1000];
|
||||
while (true) {
|
||||
out.write(data);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
interrupter.cancel(true);
|
||||
Thread.interrupted(); // clear interrupt
|
||||
}
|
||||
assertTrue(s.isClosed());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test write when channel is configured non-blocking
|
||||
*/
|
||||
public void testWrite4() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
sc.configureBlocking(false);
|
||||
OutputStream out = sc.socket().getOutputStream();
|
||||
expectThrows(IllegalBlockingModeException.class, () -> out.write(99));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read when there are bytes available and another thread is blocked
|
||||
* in write
|
||||
*/
|
||||
public void testConcurrentReadWrite1() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
|
||||
// block thread in write
|
||||
execute(() -> {
|
||||
var data = new byte[64*1024];
|
||||
OutputStream out = s.getOutputStream();
|
||||
for (;;) {
|
||||
out.write(data);
|
||||
}
|
||||
});
|
||||
Thread.sleep(1000); // give writer time to block
|
||||
|
||||
// test read when bytes are available
|
||||
peer.getOutputStream().write(99);
|
||||
int n = s.getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read blocking when another thread is blocked in write
|
||||
*/
|
||||
public void testConcurrentReadWrite2() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
|
||||
// block thread in write
|
||||
execute(() -> {
|
||||
var data = new byte[64*1024];
|
||||
OutputStream out = s.getOutputStream();
|
||||
for (;;) {
|
||||
out.write(data);
|
||||
}
|
||||
});
|
||||
Thread.sleep(1000); // give writer time to block
|
||||
|
||||
// test read blocking until bytes are available
|
||||
scheduleWrite(peer.getOutputStream(), 99, 500);
|
||||
int n = s.getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test writing when another thread is blocked in read
|
||||
*/
|
||||
public void testConcurrentReadWrite3() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
|
||||
// block thread in read
|
||||
execute(() -> {
|
||||
s.getInputStream().read();
|
||||
});
|
||||
Thread.sleep(100); // give reader time to block
|
||||
|
||||
// test write
|
||||
s.getOutputStream().write(99);
|
||||
int n = peer.getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test timed read when there are bytes available and another thread is
|
||||
* blocked in write
|
||||
*/
|
||||
public void testConcurrentTimedReadWrite1() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
|
||||
// block thread in write
|
||||
execute(() -> {
|
||||
var data = new byte[64*1024];
|
||||
OutputStream out = s.getOutputStream();
|
||||
for (;;) {
|
||||
out.write(data);
|
||||
}
|
||||
});
|
||||
Thread.sleep(1000); // give writer time to block
|
||||
|
||||
// test read when bytes are available
|
||||
peer.getOutputStream().write(99);
|
||||
s.setSoTimeout(60_000);
|
||||
int n = s.getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test timed read blocking when another thread is blocked in write
|
||||
*/
|
||||
public void testConcurrentTimedReadWrite2() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
|
||||
// block thread in write
|
||||
execute(() -> {
|
||||
var data = new byte[64*1024];
|
||||
OutputStream out = s.getOutputStream();
|
||||
for (;;) {
|
||||
out.write(data);
|
||||
}
|
||||
});
|
||||
Thread.sleep(1000); // give writer time to block
|
||||
|
||||
// test read blocking until bytes are available
|
||||
scheduleWrite(peer.getOutputStream(), 99, 500);
|
||||
s.setSoTimeout(60_000);
|
||||
int n = s.getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test writing when another thread is blocked in read
|
||||
*/
|
||||
public void testConcurrentTimedReadWrite3() throws Exception {
|
||||
withConnection((sc, peer) -> {
|
||||
Socket s = sc.socket();
|
||||
|
||||
// block thread in read
|
||||
execute(() -> {
|
||||
s.setSoTimeout(60_000);
|
||||
s.getInputStream().read();
|
||||
});
|
||||
Thread.sleep(100); // give reader time to block
|
||||
|
||||
// test write
|
||||
s.getOutputStream().write(99);
|
||||
int n = peer.getInputStream().read();
|
||||
assertEquals(n, 99);
|
||||
});
|
||||
}
|
||||
|
||||
// -- test infrastructure --
|
||||
|
||||
interface ThrowingTask {
|
||||
void run() throws Exception;
|
||||
}
|
||||
|
||||
interface ThrowingBiConsumer<T, U> {
|
||||
void accept(T t, U u) throws Exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the consumer with a connected pair of socket channel and socket
|
||||
*/
|
||||
static void withConnection(ThrowingBiConsumer<SocketChannel, Socket> consumer)
|
||||
throws Exception
|
||||
{
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
try (SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress())) {
|
||||
try (Socket peer = ss.accept()) {
|
||||
consumer.accept(sc, peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Future<?> scheduleWrite(OutputStream out, byte[] data, long delay) {
|
||||
return schedule(() -> {
|
||||
try {
|
||||
out.write(data);
|
||||
} catch (IOException ioe) { }
|
||||
}, delay);
|
||||
}
|
||||
|
||||
static Future<?> scheduleWrite(OutputStream out, int b, long delay) {
|
||||
return scheduleWrite(out, new byte[] { (byte)b }, delay);
|
||||
}
|
||||
|
||||
static Future<?> scheduleClose(Closeable c, long delay) {
|
||||
return schedule(() -> {
|
||||
try {
|
||||
c.close();
|
||||
} catch (IOException ioe) { }
|
||||
}, delay);
|
||||
}
|
||||
|
||||
static Future<?> scheduleInterrupt(Thread t, long delay) {
|
||||
return schedule(() -> t.interrupt(), delay);
|
||||
}
|
||||
|
||||
static Future<?> schedule(Runnable task, long delay) {
|
||||
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
try {
|
||||
return executor.schedule(task, delay, TimeUnit.MILLISECONDS);
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
static Future<?> execute(ThrowingTask task) {
|
||||
ExecutorService pool = Executors.newFixedThreadPool(1);
|
||||
try {
|
||||
return pool.submit(() -> {
|
||||
task.run();
|
||||
return null;
|
||||
});
|
||||
} finally {
|
||||
pool.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
260
test/jdk/java/nio/channels/SocketChannel/AsyncCloseChannel.java
Normal file
260
test/jdk/java/nio/channels/SocketChannel/AsyncCloseChannel.java
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 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 6285901 6501089
|
||||
* @summary Check no data is written to wrong socket channel during async closing.
|
||||
* @requires (os.family != "windows")
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
public class AsyncCloseChannel {
|
||||
static volatile boolean failed = false;
|
||||
static volatile boolean keepGoing = true;
|
||||
static int maxAcceptCount = 100;
|
||||
static volatile int acceptCount = 0;
|
||||
static int sensorPort;
|
||||
static int targetPort;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
Thread ss = new SensorServer(); ss.start();
|
||||
Thread ts = new TargetServer(); ts.start();
|
||||
|
||||
sensorPort = ((ServerThread)ss).server.getLocalPort();
|
||||
targetPort = ((ServerThread)ts).server.getLocalPort();
|
||||
|
||||
Thread sc = new SensorClient(); sc.start();
|
||||
Thread tc = new TargetClient(); tc.start();
|
||||
|
||||
while(acceptCount < maxAcceptCount && !failed) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
keepGoing = false;
|
||||
try {
|
||||
ss.interrupt();
|
||||
ts.interrupt();
|
||||
sc.interrupt();
|
||||
tc.interrupt();
|
||||
} catch (Exception e) {}
|
||||
if (failed)
|
||||
throw new RuntimeException("AsyncCloseChannel2 failed after <"
|
||||
+ acceptCount + "> times of accept!");
|
||||
}
|
||||
|
||||
static class SensorServer extends ServerThread {
|
||||
public void runEx() throws Exception {
|
||||
while(keepGoing) {
|
||||
try {
|
||||
final Socket s = server.accept();
|
||||
new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
int c = s.getInputStream().read();
|
||||
if(c != -1) {
|
||||
// No data is ever written to the peer's socket!
|
||||
System.err.println("Oops: read a character: "
|
||||
+ (char) c);
|
||||
failed = true;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
closeIt(s);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
} catch (IOException ex) {
|
||||
System.err.println("Exception on sensor server " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class TargetServer extends ServerThread {
|
||||
public void runEx() throws Exception {
|
||||
while (keepGoing) {
|
||||
try {
|
||||
final Socket s = server.accept();
|
||||
acceptCount++;
|
||||
new Thread() {
|
||||
public void run() {
|
||||
boolean empty = true;
|
||||
try {
|
||||
while (keepGoing) {
|
||||
int c = s.getInputStream().read();
|
||||
if(c == -1) {
|
||||
if(!empty)
|
||||
break;
|
||||
}
|
||||
empty = false;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
closeIt(s);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
} catch (IOException ex) {
|
||||
System.err.println("Exception on target server " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class SensorClient extends Thread {
|
||||
private static boolean wake;
|
||||
private static SensorClient theClient;
|
||||
public void run() {
|
||||
while (keepGoing) {
|
||||
Socket s = null;
|
||||
try {
|
||||
s = new Socket();
|
||||
synchronized(this) {
|
||||
while(!wake && keepGoing) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException ex) { }
|
||||
}
|
||||
wake = false;
|
||||
}
|
||||
s.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), sensorPort));
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException ex) { }
|
||||
} catch (IOException ex) {
|
||||
System.err.println("Exception on sensor client " + ex.getMessage());
|
||||
} finally {
|
||||
if(s != null) {
|
||||
try {
|
||||
s.close();
|
||||
} catch(IOException ex) { ex.printStackTrace();}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SensorClient() {
|
||||
theClient = this;
|
||||
}
|
||||
|
||||
public static void wakeMe() {
|
||||
synchronized(theClient) {
|
||||
wake = true;
|
||||
theClient.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class TargetClient extends Thread {
|
||||
volatile boolean ready = false;
|
||||
public void run() {
|
||||
while(keepGoing) {
|
||||
try {
|
||||
final SocketChannel s = SocketChannel.open(
|
||||
new InetSocketAddress(InetAddress.getLoopbackAddress(), targetPort));
|
||||
s.finishConnect();
|
||||
s.socket().setSoLinger(false, 0);
|
||||
ready = false;
|
||||
Thread t = new Thread() {
|
||||
public void run() {
|
||||
ByteBuffer b = ByteBuffer.allocate(1);
|
||||
try {
|
||||
for(;;) {
|
||||
b.clear();
|
||||
b.put((byte) 'A');
|
||||
b.flip();
|
||||
s.write(b);
|
||||
ready = true;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if(!(ex instanceof ClosedChannelException))
|
||||
System.err.println("Exception in target client child "
|
||||
+ ex.toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
t.start();
|
||||
while(!ready && keepGoing) {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException ex) {}
|
||||
}
|
||||
s.close();
|
||||
SensorClient.wakeMe();
|
||||
t.join();
|
||||
} catch (IOException ex) {
|
||||
System.err.println("Exception in target client parent "
|
||||
+ ex.getMessage());
|
||||
} catch (InterruptedException ex) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class ServerThread extends Thread {
|
||||
ServerSocket server;
|
||||
public ServerThread() {
|
||||
super();
|
||||
try {
|
||||
server = new ServerSocket(0);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void interrupt() {
|
||||
super.interrupt();
|
||||
if (server != null) {
|
||||
try {
|
||||
server.close();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void run() {
|
||||
try {
|
||||
runEx();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
abstract void runEx() throws Exception;
|
||||
}
|
||||
|
||||
public static void closeIt(Socket s) {
|
||||
try {
|
||||
if(s != null)
|
||||
s.close();
|
||||
} catch (IOException ex) { }
|
||||
}
|
||||
}
|
||||
84
test/jdk/java/nio/channels/SocketChannel/Basic.java
Normal file
84
test/jdk/java/nio/channels/SocketChannel/Basic.java
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 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
|
||||
* @summary Unit test for socket channels
|
||||
* @library .. /test/lib
|
||||
* @build jdk.test.lib.Utils TestServers
|
||||
* @run main Basic
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.charset.*;
|
||||
|
||||
|
||||
public class Basic {
|
||||
|
||||
static java.io.PrintStream out = System.out;
|
||||
|
||||
static void test(TestServers.DayTimeServer daytimeServer) throws Exception {
|
||||
InetSocketAddress isa
|
||||
= new InetSocketAddress(daytimeServer.getAddress(),
|
||||
daytimeServer.getPort());
|
||||
SocketChannel sc = SocketChannel.open(isa);
|
||||
out.println("opened: " + sc);
|
||||
/*
|
||||
out.println("opts: " + sc.options());
|
||||
((SocketOpts.IP.TCP)sc.options())
|
||||
.noDelay(true)
|
||||
.typeOfService(SocketOpts.IP.TOS_THROUGHPUT)
|
||||
.broadcast(true)
|
||||
.keepAlive(true)
|
||||
.linger(42)
|
||||
.outOfBandInline(true)
|
||||
.receiveBufferSize(128)
|
||||
.sendBufferSize(128)
|
||||
.reuseAddress(true);
|
||||
out.println(" " + sc.options());
|
||||
*/
|
||||
// sc.connect(isa);
|
||||
out.println("connected: " + sc);
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(100);
|
||||
int n = sc.read(bb);
|
||||
bb.position(bb.position() - 2); // Drop CRLF
|
||||
bb.flip();
|
||||
CharBuffer cb = Charset.forName("US-ASCII").newDecoder().decode(bb);
|
||||
out.println(isa + " says: \"" + cb + "\"");
|
||||
sc.socket().shutdownInput();
|
||||
out.println("ishut: " + sc);
|
||||
sc.socket().shutdownOutput();
|
||||
out.println("oshut: " + sc);
|
||||
sc.close();
|
||||
out.println("closed: " + sc);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (TestServers.DayTimeServer dayTimeServer
|
||||
= TestServers.DayTimeServer.startNewServer(100)) {
|
||||
test(dayTimeServer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
61
test/jdk/java/nio/channels/SocketChannel/BigReadWrite.java
Normal file
61
test/jdk/java/nio/channels/SocketChannel/BigReadWrite.java
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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
|
||||
* @requires os.family == "Linux"
|
||||
* @bug 4863423
|
||||
* @summary Test Util caching policy
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
|
||||
public class BigReadWrite {
|
||||
|
||||
static int testSize = 15;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
FileOutputStream fos = new FileOutputStream("/dev/zero");
|
||||
FileChannel fc = fos.getChannel();
|
||||
|
||||
// Three small writes to fill up the Util cache
|
||||
ByteBuffer buf = ByteBuffer.allocate(900);
|
||||
fc.write(buf);
|
||||
buf = ByteBuffer.allocate(950);
|
||||
fc.write(buf);
|
||||
buf = ByteBuffer.allocate(975);
|
||||
fc.write(buf);
|
||||
buf = ByteBuffer.allocate(4419000);
|
||||
|
||||
// Now initiate large write to create larger direct buffers
|
||||
long iterations = 0;
|
||||
while (iterations < 50) {
|
||||
fc.write(buf);
|
||||
buf.rewind();
|
||||
iterations++;
|
||||
}
|
||||
// Clean up
|
||||
fc.close();
|
||||
}
|
||||
}
|
||||
50
test/jdk/java/nio/channels/SocketChannel/Bind.java
Normal file
50
test/jdk/java/nio/channels/SocketChannel/Bind.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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 4774315
|
||||
* @summary Test if bind problems cause BindException not SocketException
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
|
||||
public class Bind {
|
||||
public static void main(String[] args) throws Exception {
|
||||
SocketChannel sc1 = SocketChannel.open();
|
||||
try {
|
||||
sc1.bind(new InetSocketAddress(0));
|
||||
int port = sc1.socket().getLocalPort();
|
||||
SocketChannel sc2 = SocketChannel.open();
|
||||
try {
|
||||
sc2.bind(new InetSocketAddress(port));
|
||||
} finally {
|
||||
sc2.close();
|
||||
}
|
||||
} catch (BindException be) {
|
||||
// Correct result
|
||||
} finally {
|
||||
sc1.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
50
test/jdk/java/nio/channels/SocketChannel/BufferSize.java
Normal file
50
test/jdk/java/nio/channels/SocketChannel/BufferSize.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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 4514230
|
||||
* @summary Test setting illegal buffer sizes
|
||||
* @library ..
|
||||
*/
|
||||
|
||||
import java.nio.channels.*;
|
||||
|
||||
public class BufferSize {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ServerSocketChannel sc = ServerSocketChannel.open();
|
||||
try {
|
||||
sc.socket().setReceiveBufferSize(-1);
|
||||
throw new Exception("Illegal size accepted");
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// correct behavior
|
||||
}
|
||||
try {
|
||||
sc.socket().setReceiveBufferSize(0);
|
||||
throw new Exception("Illegal size accepted");
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// correct behavior
|
||||
}
|
||||
sc.close();
|
||||
}
|
||||
}
|
||||
72
test/jdk/java/nio/channels/SocketChannel/Close.java
Normal file
72
test/jdk/java/nio/channels/SocketChannel/Close.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 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 4458266
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
|
||||
|
||||
public class Close {
|
||||
|
||||
static SelectionKey open() throws IOException {
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
Selector sel = Selector.open();
|
||||
sc.configureBlocking(false);
|
||||
return sc.register(sel, SelectionKey.OP_READ);
|
||||
}
|
||||
|
||||
static void check(SelectionKey sk) throws IOException {
|
||||
if (sk.isValid())
|
||||
throw new RuntimeException("Key still valid");
|
||||
if (sk.channel().isOpen())
|
||||
throw new RuntimeException("Channel still open");
|
||||
// if (!((SocketChannel)sk.channel()).socket().isClosed())
|
||||
// throw new RuntimeException("Socket still open");
|
||||
}
|
||||
|
||||
static void testSocketClose() throws IOException {
|
||||
SelectionKey sk = open();
|
||||
//((SocketChannel)sk.channel()).socket().close();
|
||||
check(sk);
|
||||
}
|
||||
|
||||
static void testChannelClose() throws IOException {
|
||||
SelectionKey sk = open();
|
||||
try {
|
||||
sk.channel().close();
|
||||
check(sk);
|
||||
} finally {
|
||||
sk.selector().close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
//## testSocketClose();
|
||||
testChannelClose();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 6380091
|
||||
*/
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.io.IOException;
|
||||
|
||||
public class CloseAfterConnect {
|
||||
public static void main(String[] args) throws Exception {
|
||||
ServerSocketChannel ssc = ServerSocketChannel.open();
|
||||
ssc.socket().bind(new InetSocketAddress(0));
|
||||
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
final SocketChannel sc = SocketChannel.open();
|
||||
final InetSocketAddress isa =
|
||||
new InetSocketAddress(lh, ssc.socket().getLocalPort());
|
||||
|
||||
// establish connection in another thread
|
||||
Runnable connector =
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
sc.connect(isa);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
Thread thr = new Thread(connector);
|
||||
thr.start();
|
||||
|
||||
// wait for connect to be established and for thread to
|
||||
// terminate
|
||||
do {
|
||||
try {
|
||||
thr.join();
|
||||
} catch (InterruptedException x) { }
|
||||
} while (thr.isAlive());
|
||||
|
||||
// check connection is established
|
||||
if (!sc.isConnected()) {
|
||||
throw new RuntimeException("SocketChannel not connected");
|
||||
}
|
||||
|
||||
// close channel - this triggered the bug as it attempted to signal
|
||||
// a thread that no longer exists
|
||||
sc.close();
|
||||
|
||||
// clean-up
|
||||
ssc.accept().close();
|
||||
ssc.close();
|
||||
}
|
||||
}
|
||||
127
test/jdk/java/nio/channels/SocketChannel/CloseDuringConnect.java
Normal file
127
test/jdk/java/nio/channels/SocketChannel/CloseDuringConnect.java
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 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 8198928
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Utils
|
||||
* @run main/timeout=480 CloseDuringConnect
|
||||
* @summary Attempt to cause a deadlock by closing a SocketChannel in one thread
|
||||
* where another thread is closing the channel after a connect fail
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.stream.IntStream;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import jdk.test.lib.Utils;
|
||||
|
||||
public class CloseDuringConnect {
|
||||
|
||||
// number of test iterations, needs to be 5-10 at least
|
||||
static final int ITERATIONS = 50;
|
||||
|
||||
// maximum delay before closing SocketChannel, in milliseconds
|
||||
static final int MAX_DELAY_BEFORE_CLOSE = 20;
|
||||
|
||||
/**
|
||||
* Invoked by a task in the thread pool to connect to a remote address.
|
||||
* The connection should never be established.
|
||||
*/
|
||||
static Void connect(SocketChannel sc, SocketAddress remote) {
|
||||
try {
|
||||
if (!sc.connect(remote)) {
|
||||
while (!sc.finishConnect()) {
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Connected, should not happen");
|
||||
} catch (IOException expected) { }
|
||||
if (sc.isConnected())
|
||||
throw new RuntimeException("isConnected return true, should not happen");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by a task in the thread pool to close a socket channel.
|
||||
*/
|
||||
static Void close(SocketChannel sc) {
|
||||
try {
|
||||
sc.close();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("close failed", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for deadlock by submitting a task to connect to the given address
|
||||
* while another task closes the socket channel.
|
||||
* @param pool the thread pool to submit or schedule tasks
|
||||
* @param remote the remote address, does not accept connections
|
||||
* @param blocking socket channel blocking mode
|
||||
* @param delay the delay, in millis, before closing the channel
|
||||
*/
|
||||
static void test(ScheduledExecutorService pool,
|
||||
SocketAddress remote,
|
||||
boolean blocking,
|
||||
long delay) {
|
||||
try {
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
sc.configureBlocking(blocking);
|
||||
Future<Void> r1 = pool.submit(() -> connect(sc, remote));
|
||||
Future<Void> r2 = pool.schedule(() -> close(sc), delay, MILLISECONDS);
|
||||
r1.get();
|
||||
r2.get();
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Test failed", t);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SocketAddress refusing = Utils.refusingEndpoint();
|
||||
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
|
||||
try {
|
||||
IntStream.range(0, ITERATIONS).forEach(i -> {
|
||||
System.out.format("Iteration %d ...%n", (i + 1));
|
||||
|
||||
// Execute the test for varying delays up to MAX_DELAY_BEFORE_CLOSE,
|
||||
// for socket channels configured both blocking and non-blocking
|
||||
IntStream.range(0, MAX_DELAY_BEFORE_CLOSE).forEach(delay -> {
|
||||
test(pool, refusing, /*blocking mode*/true, delay);
|
||||
test(pool, refusing, /*blocking mode*/false, delay);
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
pool.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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
|
||||
* @summary Test asynchronous close during a blocking write
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.net.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.Random;
|
||||
|
||||
public class CloseDuringWrite {
|
||||
|
||||
static final Random rand = new Random();
|
||||
|
||||
/**
|
||||
* A task that closes a Closeable
|
||||
*/
|
||||
static class Closer implements Callable<Void> {
|
||||
final Closeable c;
|
||||
Closer(Closeable c) {
|
||||
this.c = c;
|
||||
}
|
||||
public Void call() throws IOException {
|
||||
c.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor();
|
||||
try {
|
||||
try (ServerSocketChannel ssc = ServerSocketChannel.open()) {
|
||||
ssc.bind(new InetSocketAddress(0));
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
int port = ssc.socket().getLocalPort();
|
||||
SocketAddress sa = new InetSocketAddress(lh, port);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(2*1024*1024);
|
||||
|
||||
for (int i=0; i<20; i++) {
|
||||
try (SocketChannel source = SocketChannel.open(sa);
|
||||
SocketChannel sink = ssc.accept())
|
||||
{
|
||||
// schedule channel to be closed
|
||||
Closer c = new Closer(source);
|
||||
int when = 1000 + rand.nextInt(2000);
|
||||
Future<Void> result = pool.schedule(c, when, TimeUnit.MILLISECONDS);
|
||||
|
||||
// the write should either succeed or else throw a
|
||||
// ClosedChannelException (more likely an
|
||||
// AsynchronousCloseException)
|
||||
try {
|
||||
for (;;) {
|
||||
int limit = rand.nextInt(bb.capacity());
|
||||
bb.position(0);
|
||||
bb.limit(limit);
|
||||
int n = source.write(bb);
|
||||
System.out.format("wrote %d, expected %d%n", n, limit);
|
||||
}
|
||||
} catch (ClosedChannelException expected) {
|
||||
System.out.println(expected + " (expected)");
|
||||
} finally {
|
||||
result.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
pool.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 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 4960962 6215050
|
||||
@summary Test if the registered SocketChannel can be closed immediately
|
||||
@run main/timeout=10 CloseRegisteredChannel
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.net.*;
|
||||
|
||||
public class CloseRegisteredChannel {
|
||||
public static void main(String[] args) throws Exception {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
ServerSocket s = server.socket ();
|
||||
s.bind (new InetSocketAddress (0));
|
||||
int port = s.getLocalPort ();
|
||||
//System.out.println ("listening on port " + port);
|
||||
|
||||
SocketChannel client = SocketChannel.open ();
|
||||
client.connect (new InetSocketAddress (InetAddress.getLoopbackAddress(), port));
|
||||
SocketChannel peer = server.accept();
|
||||
peer.configureBlocking(true);
|
||||
|
||||
Selector selector = Selector.open ();
|
||||
client.configureBlocking (false);
|
||||
SelectionKey key = client.register (
|
||||
selector, SelectionKey.OP_READ, null
|
||||
);
|
||||
client.close();
|
||||
//System.out.println ("client.isOpen = " + client.isOpen());
|
||||
System.out.println ("Will hang here...");
|
||||
int nb = peer.read(ByteBuffer.allocate (1024));
|
||||
//System.out.println("read nb=" + nb);
|
||||
|
||||
selector.close();
|
||||
server.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* 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
|
||||
@bug 4726957 4724030 6232954
|
||||
@summary Test if the SocketChannel with timeout set can be closed immediately
|
||||
@run main/timeout=20 CloseTimeoutChannel
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.net.*;
|
||||
|
||||
public class CloseTimeoutChannel {
|
||||
public static void main(String args[]) throws Exception {
|
||||
int port = -1;
|
||||
try {
|
||||
ServerSocketChannel listener=ServerSocketChannel.open();
|
||||
listener.socket().bind(new InetSocketAddress(0));
|
||||
port = listener.socket().getLocalPort();
|
||||
AcceptorThread thread=new AcceptorThread(listener);
|
||||
thread.start();
|
||||
} catch (IOException e) {
|
||||
System.out.println("Mysterious IO problem");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
//Establish connection. Bug only happens if we open with channel.
|
||||
try {
|
||||
System.out.println("Establishing connection");
|
||||
Socket socket=SocketChannel.open(
|
||||
new InetSocketAddress(InetAddress.getLoopbackAddress(), port)).socket();
|
||||
OutputStream out=socket.getOutputStream();
|
||||
InputStream in=socket.getInputStream();
|
||||
|
||||
System.out.println("1. Writing byte 1");
|
||||
out.write((byte)1);
|
||||
|
||||
int n=read(socket, in);
|
||||
System.out.println("Read byte "+n+"\n");
|
||||
|
||||
System.out.println("3. Writing byte 3");
|
||||
out.write((byte)3);
|
||||
|
||||
System.out.println("Closing");
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("Mysterious IO problem");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Reads one byte from in, which must be s.getInputStream. */
|
||||
private static int read(Socket s, InputStream in) throws IOException {
|
||||
try {
|
||||
s.setSoTimeout(8000); //causes a bug!
|
||||
return in.read();
|
||||
} finally {
|
||||
s.setSoTimeout(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Server thread */
|
||||
static class AcceptorThread extends Thread {
|
||||
final String INDENT="\t\t\t\t";
|
||||
ServerSocketChannel _listener;
|
||||
/** @param listener MUST be bound to a port */
|
||||
AcceptorThread(ServerSocketChannel listener) {
|
||||
_listener=listener;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) { }
|
||||
|
||||
System.out.println(INDENT+"Listening on port "+
|
||||
_listener.socket().getLocalPort());
|
||||
ByteBuffer buf=ByteBuffer.allocate(5);
|
||||
Socket client=_listener.accept().socket();
|
||||
System.out.println(INDENT+"Accepted client");
|
||||
|
||||
OutputStream out=client.getOutputStream();
|
||||
InputStream in=client.getInputStream();
|
||||
|
||||
int n=in.read();
|
||||
System.out.println(INDENT+"Read byte "+n+"\n");
|
||||
|
||||
System.out.println(INDENT+"2. Writing byte 2");
|
||||
out.write((byte)2);
|
||||
|
||||
n=in.read();
|
||||
System.out.println(INDENT+"Read byte "+n+"\n");
|
||||
|
||||
n=in.read();
|
||||
System.out.println(INDENT+"Read byte "
|
||||
+(n<0 ? "EOF" : Integer.toString(n)));
|
||||
|
||||
System.out.println(INDENT+"Closing");
|
||||
client.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println(INDENT+"Error accepting!");
|
||||
} finally {
|
||||
try { _listener.close(); } catch (IOException ignore) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
121
test/jdk/java/nio/channels/SocketChannel/Connect.java
Normal file
121
test/jdk/java/nio/channels/SocketChannel/Connect.java
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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 4650679 8037360
|
||||
* @summary Unit test for socket channels
|
||||
* @library .. /test/lib
|
||||
* @build jdk.test.lib.Utils TestServers
|
||||
* @run main Connect
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Connect {
|
||||
|
||||
private static final long INCREMENTAL_DELAY = 30L * 1000L;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
try (TestServers.EchoServer echoServer
|
||||
= TestServers.EchoServer.startNewServer(1000)) {
|
||||
test1(echoServer);
|
||||
}
|
||||
try {
|
||||
test1(TestServers.RefusingServer.newRefusingServer());
|
||||
throw new Exception("Refused connection throws no exception");
|
||||
} catch (ConnectException ce) {
|
||||
// Correct result
|
||||
}
|
||||
}
|
||||
|
||||
static void test1(TestServers.AbstractServer server) throws Exception {
|
||||
Selector selector;
|
||||
SocketChannel sc;
|
||||
SelectionKey sk;
|
||||
InetSocketAddress isa = new InetSocketAddress(
|
||||
server.getAddress(), server.getPort());
|
||||
sc = SocketChannel.open();
|
||||
sc.configureBlocking(false);
|
||||
|
||||
selector = Selector.open();
|
||||
sk = sc.register(selector, SelectionKey.OP_CONNECT);
|
||||
if (sc.connect(isa)) {
|
||||
System.err.println("Connected immediately!");
|
||||
sc.close();
|
||||
selector.close();
|
||||
return;
|
||||
} else {
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(100);
|
||||
buf.asCharBuffer().put(new String(
|
||||
"The quick brown fox jumped over the lazy dog."
|
||||
).toCharArray());
|
||||
buf.flip();
|
||||
long startTime = System.currentTimeMillis();
|
||||
while(true) {
|
||||
selector.select(INCREMENTAL_DELAY);
|
||||
Set selectedKeys = selector.selectedKeys();
|
||||
|
||||
if(selectedKeys.isEmpty()) {
|
||||
System.err.println("Elapsed time without response: " +
|
||||
(System.currentTimeMillis() -
|
||||
startTime) / 1000L + " seconds.");
|
||||
}
|
||||
else if(!selectedKeys.contains(sk))
|
||||
{
|
||||
System.err.println("Got wrong event about selection key.");
|
||||
} else {
|
||||
System.err.println("Got event for our selection key.");
|
||||
if(sk.isConnectable()) {
|
||||
if(sc.finishConnect()) {
|
||||
if(sc.isConnected()) {
|
||||
System.err.println("Successful connect.");
|
||||
sk.interestOps(SelectionKey.OP_WRITE);
|
||||
sc.write(buf);
|
||||
} else {
|
||||
System.err.println(
|
||||
"Finish connect completed incorrectly.");
|
||||
}
|
||||
} else {
|
||||
System.err.println(
|
||||
"key incorrectly indicated socket channel connectable.");
|
||||
}
|
||||
}
|
||||
if(sk.isWritable() && (buf.remaining() > 0)) {
|
||||
sc.write(buf);
|
||||
}
|
||||
if(buf.remaining() == 0) {
|
||||
System.err.println(
|
||||
"SUCCESS! buffer contents were sent.");
|
||||
sc.close();
|
||||
selector.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
selectedKeys.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
286
test/jdk/java/nio/channels/SocketChannel/ConnectState.java
Normal file
286
test/jdk/java/nio/channels/SocketChannel/ConnectState.java
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* 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
|
||||
* @summary Test socket-channel connection-state transitions
|
||||
* @library .. /test/lib
|
||||
* @build jdk.test.lib.Utils TestServers
|
||||
* @run main ConnectState
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
|
||||
public class ConnectState {
|
||||
|
||||
static PrintStream log = System.err;
|
||||
|
||||
static InetSocketAddress remote;
|
||||
|
||||
final static int ST_UNCONNECTED = 0;
|
||||
final static int ST_PENDING = 1;
|
||||
final static int ST_CONNECTED = 2;
|
||||
final static int ST_CLOSED = 3;
|
||||
final static int ST_PENDING_OR_CONNECTED = 4;
|
||||
// NO exceptions expected
|
||||
final static Collection<Class<?>> NONE = Collections.emptySet();
|
||||
|
||||
// make a set of expected exception.
|
||||
static Collection<Class<?>> expectedExceptions(Class<?>... expected) {
|
||||
final Collection<Class<?>> exceptions;
|
||||
if (expected.length == 0) {
|
||||
exceptions = NONE;
|
||||
} else if (expected.length == 1) {
|
||||
assert expected[0] != null;
|
||||
exceptions = Collections.<Class<?>>singleton(expected[0]);
|
||||
} else {
|
||||
exceptions = new HashSet<>(Arrays.asList(expected));
|
||||
}
|
||||
return exceptions;
|
||||
}
|
||||
|
||||
static abstract class Test {
|
||||
|
||||
abstract String go(SocketChannel sc) throws Exception;
|
||||
|
||||
static void check(boolean test, String desc) throws Exception {
|
||||
if (!test)
|
||||
throw new Exception("Incorrect state: " + desc);
|
||||
}
|
||||
|
||||
static void check(SocketChannel sc, int state) throws Exception {
|
||||
switch (state) {
|
||||
case ST_UNCONNECTED:
|
||||
check(!sc.isConnected(), "!isConnected");
|
||||
check(!sc.isConnectionPending(), "!isConnectionPending");
|
||||
check(sc.isOpen(), "isOpen");
|
||||
break;
|
||||
case ST_PENDING:
|
||||
check(!sc.isConnected(), "!isConnected");
|
||||
check(sc.isConnectionPending(), "isConnectionPending");
|
||||
check(sc.isOpen(), "isOpen");
|
||||
break;
|
||||
case ST_CONNECTED:
|
||||
check(sc.isConnected(), "isConnected");
|
||||
check(!sc.isConnectionPending(), "!isConnectionPending");
|
||||
check(sc.isOpen(), "isOpen");
|
||||
break;
|
||||
case ST_CLOSED:
|
||||
check(sc.isConnected(), "isConnected");
|
||||
check(!sc.isConnectionPending(), "!isConnectionPending");
|
||||
check(sc.isOpen(), "isOpen");
|
||||
break;
|
||||
case ST_PENDING_OR_CONNECTED:
|
||||
check(sc.isConnected() || sc.isConnectionPending(),
|
||||
"isConnected || isConnectionPending");
|
||||
check(sc.isOpen(), "isOpen");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Test(String name, Class<?> exception, int state) throws Exception {
|
||||
this(name, expectedExceptions(exception), state);
|
||||
}
|
||||
|
||||
// On some architecture we may need to accept several exceptions.
|
||||
// For instance on Solaris, when using a server colocated on the
|
||||
// machine we cannot guarantee that we will get a
|
||||
// ConnectionPendingException when connecting twice on the same
|
||||
// non-blocking socket. We may instead get an
|
||||
// AlreadyConnectedException, which is also valid: it simply means
|
||||
// that the first connection has been immediately accepted.
|
||||
Test(String name, Collection<Class<?>> exceptions, int state)
|
||||
throws Exception {
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
String note;
|
||||
try {
|
||||
try {
|
||||
note = go(sc);
|
||||
} catch (Exception x) {
|
||||
Class<?> expectedExceptionClass = null;
|
||||
for (Class<?> exception : exceptions) {
|
||||
if (exception.isInstance(x)) {
|
||||
log.println(name + ": As expected: "
|
||||
+ x);
|
||||
expectedExceptionClass = exception;
|
||||
check(sc, state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (expectedExceptionClass == null
|
||||
&& !exceptions.isEmpty()) {
|
||||
// we had an exception, but it's not of the set of
|
||||
// exceptions we expected.
|
||||
throw new Exception(name
|
||||
+ ": Incorrect exception",
|
||||
x);
|
||||
} else if (exceptions.isEmpty()) {
|
||||
// we didn't expect any exception
|
||||
throw new Exception(name
|
||||
+ ": Unexpected exception",
|
||||
x);
|
||||
}
|
||||
// if we reach here, we have our expected exception
|
||||
assert expectedExceptionClass != null;
|
||||
return;
|
||||
}
|
||||
if (!exceptions.isEmpty()) {
|
||||
throw new Exception(name
|
||||
+ ": Expected exception not thrown: "
|
||||
+ exceptions.iterator().next());
|
||||
}
|
||||
check(sc, state);
|
||||
log.println(name + ": Returned normally"
|
||||
+ ((note != null) ? ": " + note : ""));
|
||||
} finally {
|
||||
if (sc.isOpen())
|
||||
sc.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void tests() throws Exception {
|
||||
log.println(remote);
|
||||
|
||||
new Test("Read unconnected", NotYetConnectedException.class,
|
||||
ST_UNCONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
ByteBuffer b = ByteBuffer.allocateDirect(1024);
|
||||
sc.read(b);
|
||||
return null;
|
||||
}};
|
||||
|
||||
new Test("Write unconnected", NotYetConnectedException.class,
|
||||
ST_UNCONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
ByteBuffer b = ByteBuffer.allocateDirect(1024);
|
||||
sc.write(b);
|
||||
return null;
|
||||
}};
|
||||
|
||||
new Test("Simple connect", NONE, ST_CONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
sc.connect(remote);
|
||||
return null;
|
||||
}};
|
||||
|
||||
new Test("Simple connect & finish", NONE, ST_CONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
sc.connect(remote);
|
||||
if (!sc.finishConnect())
|
||||
throw new Exception("finishConnect returned false");
|
||||
return null;
|
||||
}};
|
||||
|
||||
new Test("Double connect",
|
||||
AlreadyConnectedException.class, ST_CONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
sc.connect(remote);
|
||||
sc.connect(remote);
|
||||
return null;
|
||||
}};
|
||||
|
||||
new Test("Finish w/o start",
|
||||
NoConnectionPendingException.class, ST_UNCONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
sc.finishConnect();
|
||||
return null;
|
||||
}};
|
||||
|
||||
// Note: using our local EchoServer rather than echo on a distant
|
||||
// host - we see that Tries to finish = 0 (instead of ~ 18).
|
||||
new Test("NB simple connect", NONE, ST_CONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
sc.configureBlocking(false);
|
||||
sc.connect(remote);
|
||||
int n = 0;
|
||||
while (!sc.finishConnect()) {
|
||||
Thread.sleep(10);
|
||||
n++;
|
||||
}
|
||||
sc.finishConnect(); // Check redundant invocation
|
||||
return ("Tries to finish = " + n);
|
||||
}};
|
||||
|
||||
// Note: using our local EchoServer rather than echo on a distant
|
||||
// host - we cannot guarantee that this test will get a
|
||||
// a ConnectionPendingException: it may get an
|
||||
// AlreadyConnectedException, so we should allow for both.
|
||||
new Test("NB double connect",
|
||||
expectedExceptions(ConnectionPendingException.class,
|
||||
AlreadyConnectedException.class),
|
||||
ST_PENDING_OR_CONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
sc.configureBlocking(false);
|
||||
sc.connect(remote);
|
||||
sc.connect(remote);
|
||||
return null;
|
||||
}};
|
||||
|
||||
new Test("NB finish w/o start",
|
||||
NoConnectionPendingException.class, ST_UNCONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
sc.configureBlocking(false);
|
||||
sc.finishConnect();
|
||||
return null;
|
||||
}};
|
||||
|
||||
new Test("NB connect, B finish", NONE, ST_CONNECTED) {
|
||||
@Override
|
||||
String go(SocketChannel sc) throws Exception {
|
||||
sc.configureBlocking(false);
|
||||
sc.connect(remote);
|
||||
sc.configureBlocking(true);
|
||||
sc.finishConnect();
|
||||
return null;
|
||||
}};
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (TestServers.EchoServer echoServer
|
||||
= TestServers.EchoServer.startNewServer(500)) {
|
||||
remote = new InetSocketAddress(echoServer.getAddress(),
|
||||
echoServer.getPort());
|
||||
tests();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright (c) 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.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeFalse;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8376290
|
||||
* @summary Verify that when a SocketChannel is registered with a Selector
|
||||
* with an interest in CONNECT operation, then SocketChannel.finishConnect()
|
||||
* throws the correct exception message, if the connect() fails
|
||||
* @run junit/othervm -Djdk.includeInExceptions=hostInfoExclSocket ${test.main.class}
|
||||
* @run junit/othervm -Djdk.includeInExceptions=hostInfo -Dcheck.relaxed=true ${test.main.class}
|
||||
*/
|
||||
class ConnectionRefusedMessage {
|
||||
|
||||
/*
|
||||
* On a non-blocking SocketChannel, registered with a Selector, this test method
|
||||
* attempts a SocketChannel.connect() against an address that is expected to return
|
||||
* Connection refused. The test then calls SocketChannel.finishConnect() when the
|
||||
* Selector makes available the ready key for this connect operation and expects
|
||||
* that finishConnect() throws a ConnectException with the expected exception message.
|
||||
*/
|
||||
@Test
|
||||
void testFinishConnect() throws Exception {
|
||||
// find a suitable address against which the connect() attempt
|
||||
// will result in a Connection refused exception
|
||||
final InetSocketAddress destAddr = findSuitableRefusedAddress();
|
||||
// skip the test if we couldn't find a port which would raise a connection refused error
|
||||
assumeTrue(destAddr != null,
|
||||
"couldn't find a suitable port which will generate a connection refused error");
|
||||
try (Selector selector = Selector.open();
|
||||
SocketChannel sc = SocketChannel.open()) {
|
||||
|
||||
// non-blocking
|
||||
sc.configureBlocking(false);
|
||||
sc.register(selector, SelectionKey.OP_CONNECT);
|
||||
|
||||
System.err.println("establishing connection to " + destAddr);
|
||||
boolean connected;
|
||||
try {
|
||||
connected = sc.connect(destAddr);
|
||||
} catch (ConnectException ce) {
|
||||
// Connect failed immediately, which is OK.
|
||||
System.err.println("SocketChannel.connect() threw ConnectException - " + ce);
|
||||
assertExceptionMessage(ce);
|
||||
return; // nothing more to test
|
||||
}
|
||||
// this test checks the exception message of a ConnectException, so it's
|
||||
// OK to skip the test if something unexpectedly accepted the connection
|
||||
assumeFalse(connected, "unexpectedly connected to " + destAddr);
|
||||
// wait for ready ops
|
||||
int numReady = selector.select(Duration.ofMinutes(10).toMillis());
|
||||
System.err.println("Num ready keys = " + numReady);
|
||||
for (SelectionKey readyKey : selector.selectedKeys()) {
|
||||
System.err.println("ready key: " + readyKey);
|
||||
assertTrue(readyKey.isConnectable(), "unexpected key, readyOps = "
|
||||
+ readyKey.readyOps());
|
||||
readyKey.cancel();
|
||||
try {
|
||||
boolean success = sc.finishConnect();
|
||||
// this test checks the exception message of a ConnectException, so it's
|
||||
// OK to skip the test if something unexpectedly accepted the connection
|
||||
assumeFalse(success, "unexpectedly connected to " + destAddr);
|
||||
// this test doesn't expect finishConnect() to return normally
|
||||
// with a return value of false
|
||||
fail("ConnectException was not thrown");
|
||||
} catch (ConnectException ce) {
|
||||
System.err.println("got (expected) ConnectException from " +
|
||||
"SocketChannel.finishConnect() - " + ce);
|
||||
// verify exception message
|
||||
assertExceptionMessage(ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertExceptionMessage(final ConnectException ce) {
|
||||
if ("Connection refused".equals(ce.getMessage())) {
|
||||
return;
|
||||
}
|
||||
if (Boolean.getBoolean("check.relaxed") && ce.getMessage() != null && ce.getMessage().startsWith("Connection refused")) {
|
||||
return;
|
||||
}
|
||||
// propagate the original exception
|
||||
fail("unexpected exception message: " + ce.getMessage(), ce);
|
||||
}
|
||||
|
||||
// Try to find a suitable port to provoke a "Connection Refused" error.
|
||||
private static InetSocketAddress findSuitableRefusedAddress() throws IOException {
|
||||
final InetAddress loopbackAddr = InetAddress.getLoopbackAddress();
|
||||
// Ports 47, 51, 61 are in the IANA reserved port list, and
|
||||
// are currently unassigned to any specific service.
|
||||
// We use them here on the assumption that there won't be
|
||||
// any service listening on them.
|
||||
InetSocketAddress destAddr = new InetSocketAddress(loopbackAddr, 47);
|
||||
try (SocketChannel sc1 = SocketChannel.open(destAddr)) {
|
||||
// we managed to connect (unexpectedly), let's try the next reserved port
|
||||
destAddr = new InetSocketAddress(loopbackAddr, 51);
|
||||
try (SocketChannel sc2 = SocketChannel.open(destAddr)) {
|
||||
}
|
||||
// we managed to connect (unexpectedly again), let's try the next reserved port
|
||||
// as a last attempt
|
||||
destAddr = new InetSocketAddress(loopbackAddr, 61);
|
||||
try (SocketChannel sc3 = SocketChannel.open(destAddr)) {
|
||||
}
|
||||
return null;
|
||||
} catch (ConnectException x) {
|
||||
}
|
||||
// the address which will generate a connection refused, when a connection is attempted
|
||||
return destAddr;
|
||||
}
|
||||
}
|
||||
247
test/jdk/java/nio/channels/SocketChannel/ConnectionReset.java
Normal file
247
test/jdk/java/nio/channels/SocketChannel/ConnectionReset.java
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 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
|
||||
* @run testng ConnectionReset
|
||||
* @summary Test behavior of SocketChannel.read and the Socket adaptor read
|
||||
* and available methods when a connection is reset
|
||||
*/
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class ConnectionReset {
|
||||
|
||||
static final int REPEAT_COUNT = 5;
|
||||
|
||||
/**
|
||||
* Tests SocketChannel.read when the connection is reset and there are no
|
||||
* bytes to read.
|
||||
*/
|
||||
public void testSocketChannelReadNoData() throws IOException {
|
||||
System.out.println("testSocketChannelReadNoData");
|
||||
withResetConnection(null, sc -> {
|
||||
ByteBuffer bb = ByteBuffer.allocate(100);
|
||||
for (int i=0; i<REPEAT_COUNT; i++) {
|
||||
try {
|
||||
sc.read(bb);
|
||||
assertTrue(false);
|
||||
} catch (IOException ioe) {
|
||||
System.out.format("read => %s (expected)%n", ioe);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SocketChannel.read when the connection is reset and there are bytes
|
||||
* to read.
|
||||
*/
|
||||
public void testSocketChannelReadData() throws IOException {
|
||||
System.out.println("testSocketChannelReadData");
|
||||
byte[] data = { 1, 2, 3 };
|
||||
withResetConnection(data, sc -> {
|
||||
int remaining = data.length;
|
||||
ByteBuffer bb = ByteBuffer.allocate(remaining + 100);
|
||||
for (int i=0; i<REPEAT_COUNT; i++) {
|
||||
try {
|
||||
int bytesRead = sc.read(bb);
|
||||
if (bytesRead == -1) {
|
||||
System.out.println("read => EOF");
|
||||
} else {
|
||||
System.out.println("read => " + bytesRead + " byte(s)");
|
||||
}
|
||||
assertTrue(bytesRead > 0);
|
||||
remaining -= bytesRead;
|
||||
assertTrue(remaining >= 0);
|
||||
} catch (IOException ioe) {
|
||||
System.out.format("read => %s%n", ioe);
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests available before Socket read when the connection is reset and there
|
||||
* are no bytes to read.
|
||||
*/
|
||||
public void testAvailableBeforeSocketReadNoData() throws IOException {
|
||||
System.out.println("testAvailableBeforeSocketReadNoData");
|
||||
withResetConnection(null, sc -> {
|
||||
Socket s = sc.socket();
|
||||
InputStream in = s.getInputStream();
|
||||
for (int i=0; i<REPEAT_COUNT; i++) {
|
||||
int bytesAvailable = in.available();
|
||||
System.out.format("available => %d%n", bytesAvailable);
|
||||
assertTrue(bytesAvailable == 0);
|
||||
try {
|
||||
int bytesRead = in.read();
|
||||
if (bytesRead == -1) {
|
||||
System.out.println("read => EOF");
|
||||
} else {
|
||||
System.out.println("read => 1 byte");
|
||||
}
|
||||
assertTrue(false);
|
||||
} catch (IOException ioe) {
|
||||
System.out.format("read => %s (expected)%n", ioe);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests available before Socket read when the connection is reset and there
|
||||
* are bytes to read.
|
||||
*/
|
||||
public void testAvailableBeforeSocketReadData() throws IOException {
|
||||
System.out.println("testAvailableBeforeSocketReadData");
|
||||
byte[] data = { 1, 2, 3 };
|
||||
withResetConnection(data, sc -> {
|
||||
Socket s = sc.socket();
|
||||
InputStream in = s.getInputStream();
|
||||
int remaining = data.length;
|
||||
for (int i=0; i<REPEAT_COUNT; i++) {
|
||||
int bytesAvailable = in.available();
|
||||
System.out.format("available => %d%n", bytesAvailable);
|
||||
assertTrue(bytesAvailable <= remaining);
|
||||
try {
|
||||
int bytesRead = in.read();
|
||||
if (bytesRead == -1) {
|
||||
System.out.println("read => EOF");
|
||||
assertTrue(false);
|
||||
} else {
|
||||
System.out.println("read => 1 byte");
|
||||
assertTrue(remaining > 0);
|
||||
remaining--;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
System.out.format("read => %s%n", ioe);
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Socket read before available when the connection is reset and there
|
||||
* are no bytes to read.
|
||||
*/
|
||||
public void testSocketReadNoDataBeforeAvailable() throws IOException {
|
||||
System.out.println("testSocketReadNoDataBeforeAvailable");
|
||||
withResetConnection(null, sc -> {
|
||||
Socket s = sc.socket();
|
||||
InputStream in = s.getInputStream();
|
||||
for (int i=0; i<REPEAT_COUNT; i++) {
|
||||
try {
|
||||
int bytesRead = in.read();
|
||||
if (bytesRead == -1) {
|
||||
System.out.println("read => EOF");
|
||||
} else {
|
||||
System.out.println("read => 1 byte");
|
||||
}
|
||||
assertTrue(false);
|
||||
} catch (IOException ioe) {
|
||||
System.out.format("read => %s (expected)%n", ioe);
|
||||
}
|
||||
int bytesAvailable = in.available();
|
||||
System.out.format("available => %d%n", bytesAvailable);
|
||||
assertTrue(bytesAvailable == 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Socket read before available when the connection is reset and there
|
||||
* are bytes to read.
|
||||
*/
|
||||
public void testSocketReadDataBeforeAvailable() throws IOException {
|
||||
System.out.println("testSocketReadDataBeforeAvailable");
|
||||
byte[] data = { 1, 2, 3 };
|
||||
withResetConnection(data, sc -> {
|
||||
Socket s = sc.socket();
|
||||
InputStream in = s.getInputStream();
|
||||
int remaining = data.length;
|
||||
for (int i=0; i<REPEAT_COUNT; i++) {
|
||||
try {
|
||||
int bytesRead = in.read();
|
||||
if (bytesRead == -1) {
|
||||
System.out.println("read => EOF");
|
||||
assertTrue(false);
|
||||
} else {
|
||||
System.out.println("read => 1 byte");
|
||||
assertTrue(remaining > 0);
|
||||
remaining--;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
System.out.format("read => %s%n", ioe);
|
||||
remaining = 0;
|
||||
}
|
||||
int bytesAvailable = in.available();
|
||||
System.out.format("available => %d%n", bytesAvailable);
|
||||
assertTrue(bytesAvailable <= remaining);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
interface ThrowingConsumer<T> {
|
||||
void accept(T t) throws IOException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a consumer with a SocketChannel connected to a peer that has closed
|
||||
* the connection with a "connection reset". The peer sends the given data
|
||||
* bytes before closing (when data is not null).
|
||||
*/
|
||||
static void withResetConnection(byte[] data, ThrowingConsumer<SocketChannel> consumer)
|
||||
throws IOException
|
||||
{
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
try (var listener = new ServerSocket()) {
|
||||
listener.bind(new InetSocketAddress(loopback, 0));
|
||||
try (var sc = SocketChannel.open()) {
|
||||
sc.connect(listener.getLocalSocketAddress());
|
||||
try (Socket peer = listener.accept()) {
|
||||
if (data != null) {
|
||||
peer.getOutputStream().write(data);
|
||||
}
|
||||
peer.setSoLinger(true, 0);
|
||||
}
|
||||
consumer.accept(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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 4915501 6303753
|
||||
|
||||
* @summary check exception translation of SocketAdaptor
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.*;
|
||||
import java.net.*;
|
||||
|
||||
public class ExceptionTranslation {
|
||||
public static void main(String args[]) throws Exception {
|
||||
InetSocketAddress iAddr = new InetSocketAddress("nosuchhostname",5182);
|
||||
try {
|
||||
SocketChannel channel = SocketChannel.open();
|
||||
channel.socket().connect(iAddr, 30000);
|
||||
throw new RuntimeException("Expected exception not thrown");
|
||||
} catch (UnknownHostException x) {
|
||||
// Expected result
|
||||
}
|
||||
|
||||
try {
|
||||
SocketChannel chan1 = SocketChannel.open();
|
||||
chan1.socket().bind(new InetSocketAddress(0));
|
||||
chan1.socket().bind(new InetSocketAddress(0));
|
||||
throw new RuntimeException("Expected exception not thrown");
|
||||
} catch(IOException e) {
|
||||
// Expected result
|
||||
}
|
||||
}
|
||||
}
|
||||
160
test/jdk/java/nio/channels/SocketChannel/FinishConnect.java
Normal file
160
test/jdk/java/nio/channels/SocketChannel/FinishConnect.java
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 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
|
||||
* @summary Test SocketChannel.finishConnect
|
||||
* @library .. /test/lib
|
||||
* @build jdk.test.lib.Utils TestServers
|
||||
* @run main FinishConnect
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.nio.charset.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class FinishConnect {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (TestServers.DayTimeServer dayTimeServer
|
||||
= TestServers.DayTimeServer.startNewServer(100)) {
|
||||
test1(dayTimeServer, true, true);
|
||||
test1(dayTimeServer, true, false);
|
||||
test1(dayTimeServer, false, true);
|
||||
test1(dayTimeServer, false, false);
|
||||
test2(dayTimeServer);
|
||||
}
|
||||
}
|
||||
|
||||
static void test1(TestServers.DayTimeServer daytimeServer,
|
||||
boolean select,
|
||||
boolean setBlocking)
|
||||
throws Exception
|
||||
{
|
||||
InetSocketAddress isa
|
||||
= new InetSocketAddress(daytimeServer.getAddress(),
|
||||
daytimeServer.getPort());
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
sc.configureBlocking(false);
|
||||
boolean connected = sc.connect(isa);
|
||||
int attempts = 0;
|
||||
|
||||
try {
|
||||
sc.connect(isa);
|
||||
throw new RuntimeException("Allowed another connect call");
|
||||
} catch (IllegalStateException ise) {
|
||||
// Correct behavior
|
||||
}
|
||||
|
||||
if (setBlocking)
|
||||
sc.configureBlocking(true);
|
||||
|
||||
if (!connected && select && !setBlocking) {
|
||||
Selector selector = SelectorProvider.provider().openSelector();
|
||||
sc.register(selector, SelectionKey.OP_CONNECT);
|
||||
while (!connected) {
|
||||
int keysAdded = selector.select(100);
|
||||
if (keysAdded > 0) {
|
||||
Set readyKeys = selector.selectedKeys();
|
||||
Iterator i = readyKeys.iterator();
|
||||
while (i.hasNext()) {
|
||||
SelectionKey sk = (SelectionKey)i.next();
|
||||
SocketChannel nextReady =
|
||||
(SocketChannel)sk.channel();
|
||||
connected = sc.finishConnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
selector.close();
|
||||
}
|
||||
|
||||
while (!connected) {
|
||||
if (attempts++ > 30)
|
||||
throw new RuntimeException("Failed to connect");
|
||||
Thread.sleep(100);
|
||||
connected = sc.finishConnect();
|
||||
}
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(100);
|
||||
int bytesRead = 0;
|
||||
int totalRead = 0;
|
||||
while (totalRead < 20) {
|
||||
bytesRead = sc.read(bb);
|
||||
if (bytesRead > 0)
|
||||
totalRead += bytesRead;
|
||||
if (bytesRead < 0)
|
||||
throw new RuntimeException("Message shorter than expected");
|
||||
}
|
||||
bb.position(bb.position() - 2); // Drop CRLF
|
||||
bb.flip();
|
||||
CharBuffer cb = Charset.forName("US-ASCII").newDecoder().decode(bb);
|
||||
System.err.println(isa + " says: \"" + cb + "\"");
|
||||
sc.close();
|
||||
}
|
||||
|
||||
static void test2(TestServers.DayTimeServer daytimeServer) throws Exception {
|
||||
InetSocketAddress isa
|
||||
= new InetSocketAddress(daytimeServer.getAddress(),
|
||||
daytimeServer.getPort());
|
||||
boolean done = false;
|
||||
int globalAttempts = 0;
|
||||
int connectSuccess = 0;
|
||||
while (!done) {
|
||||
// When using a local daytime server it is not always possible
|
||||
// to get a pending connection, as sc.connect(isa) may always
|
||||
// return true.
|
||||
// So we're going to throw the exception only if there was
|
||||
// at least 1 case where we did not manage to connect.
|
||||
if (globalAttempts++ > 50) {
|
||||
if (globalAttempts == connectSuccess + 1) {
|
||||
System.out.println("Can't fully test on "
|
||||
+ System.getProperty("os.name"));
|
||||
break;
|
||||
}
|
||||
throw new RuntimeException("Failed to connect");
|
||||
}
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
sc.configureBlocking(false);
|
||||
boolean connected = sc.connect(isa);
|
||||
int localAttempts = 0;
|
||||
while (!connected) {
|
||||
if (localAttempts++ > 500)
|
||||
throw new RuntimeException("Failed to connect");
|
||||
connected = sc.finishConnect();
|
||||
if (connected) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
Thread.sleep(10);
|
||||
}
|
||||
if (connected) {
|
||||
connectSuccess++;
|
||||
}
|
||||
sc.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
69
test/jdk/java/nio/channels/SocketChannel/GetChannel.java
Normal file
69
test/jdk/java/nio/channels/SocketChannel/GetChannel.java
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4403255
|
||||
* @summary Tests old streams using channels in socket case
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class GetChannel {
|
||||
public static void main(String args[]) throws Exception {
|
||||
InetAddress sin = null;
|
||||
Socket soc = null,soc1 = null;
|
||||
InputStream is = null;
|
||||
OutputStream os = null;
|
||||
ServerSocket srv = null;
|
||||
int port = 0;
|
||||
int tout = 1000;
|
||||
|
||||
sin = InetAddress.getLocalHost();
|
||||
srv = new ServerSocket(port);
|
||||
port = srv.getLocalPort();
|
||||
soc = new Socket(sin, port);
|
||||
soc1 = srv.accept();
|
||||
|
||||
BufferedReader bin = new BufferedReader(
|
||||
new InputStreamReader(soc.getInputStream()));
|
||||
BufferedWriter bout = new BufferedWriter(
|
||||
new OutputStreamWriter(soc1.getOutputStream()));
|
||||
|
||||
bout.write("hello");
|
||||
bout.newLine();
|
||||
bout.flush();
|
||||
|
||||
String reply = bin.readLine();
|
||||
if (!reply.equals("hello"))
|
||||
throw new RuntimeException("Test failed");
|
||||
|
||||
soc.close();
|
||||
soc1.close();
|
||||
srv.close();
|
||||
}
|
||||
}
|
||||
192
test/jdk/java/nio/channels/SocketChannel/Hangup.java
Normal file
192
test/jdk/java/nio/channels/SocketChannel/Hangup.java
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* 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 4617165
|
||||
* @summary Ensure that socket hangups are handled correctly
|
||||
* @library ..
|
||||
* @build TestUtil
|
||||
* @run main Hangup
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class Hangup {
|
||||
|
||||
static PrintStream log = System.err;
|
||||
static int failures = 0;
|
||||
|
||||
private static class Failure
|
||||
extends RuntimeException
|
||||
{
|
||||
|
||||
Failure(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void doSelect(Selector sel, SelectionKey sk, int count)
|
||||
throws IOException
|
||||
{
|
||||
int n = sel.select();
|
||||
if (n != 1)
|
||||
throw new Failure("Select returned zero");
|
||||
Set sks = sel.selectedKeys();
|
||||
if (sks.size() != 1)
|
||||
throw new Failure("Wrong size for selected-key set: "
|
||||
+ sks.size());
|
||||
if (!sks.remove(sk))
|
||||
throw new Failure("Key not in selected-key set");
|
||||
log.println("S: Socket selected #" + count);
|
||||
}
|
||||
|
||||
static void dally() {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException x) { }
|
||||
}
|
||||
|
||||
static void test(boolean writeFromClient, boolean readAfterClose)
|
||||
throws IOException
|
||||
{
|
||||
|
||||
ServerSocketChannel ssc = null;
|
||||
SocketChannel cl = null; // client end
|
||||
SocketChannel sv = null; // server end
|
||||
Selector sel = null;
|
||||
|
||||
log.println();
|
||||
log.println("Test: writeFromClient = " + writeFromClient
|
||||
+ ", readAfterClose = " + readAfterClose);
|
||||
|
||||
try {
|
||||
|
||||
int ns = 0; // Number of selection operations done
|
||||
|
||||
// Set up server socket
|
||||
ssc = ServerSocketChannel.open();
|
||||
SocketAddress sa = TestUtil.bindToRandomPort(ssc);
|
||||
log.println("S: Listening on port "
|
||||
+ ssc.socket().getLocalPort());
|
||||
|
||||
// Connect client
|
||||
cl = SocketChannel.open(sa);
|
||||
log.println("C: Connected via port "
|
||||
+ cl.socket().getLocalPort());
|
||||
|
||||
// Accept client connection
|
||||
sv = ssc.accept();
|
||||
log.println("S: Client connection accepted");
|
||||
|
||||
// Create selector and register server side
|
||||
sel = Selector.open();
|
||||
sv.configureBlocking(false);
|
||||
SelectionKey sk = sv.register(sel, SelectionKey.OP_READ);
|
||||
|
||||
ByteBuffer stuff = ByteBuffer.allocate(10);
|
||||
int n;
|
||||
|
||||
if (writeFromClient) {
|
||||
|
||||
// Write from client, read from server
|
||||
|
||||
stuff.clear();
|
||||
if (cl.write(stuff) != stuff.capacity())
|
||||
throw new Failure("Incorrect number of bytes written");
|
||||
log.println("C: Wrote stuff");
|
||||
dally();
|
||||
|
||||
doSelect(sel, sk, ++ns);
|
||||
|
||||
stuff.clear();
|
||||
if (sv.read(stuff) != stuff.capacity())
|
||||
throw new Failure("Wrong number of bytes read");
|
||||
log.println("S: Read stuff");
|
||||
}
|
||||
|
||||
// Close client side
|
||||
cl.close();
|
||||
log.println("C: Socket closed");
|
||||
dally();
|
||||
|
||||
// Select again
|
||||
doSelect(sel, sk, ++ns);
|
||||
|
||||
if (readAfterClose) {
|
||||
// Read from client after client has disconnected
|
||||
stuff.clear();
|
||||
if (sv.read(stuff) != -1)
|
||||
throw new Failure("Wrong number of bytes read");
|
||||
log.println("S: Read EOF");
|
||||
}
|
||||
|
||||
// Select a couple more times just to make sure we're doing
|
||||
// the right thing
|
||||
|
||||
doSelect(sel, sk, ++ns);
|
||||
doSelect(sel, sk, ++ns);
|
||||
|
||||
} finally {
|
||||
if (ssc != null)
|
||||
ssc.close();
|
||||
if (cl != null)
|
||||
cl.close();
|
||||
if (sv != null)
|
||||
sv.close();
|
||||
if (sel != null)
|
||||
sel.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
for (boolean writeFromClient = false;; writeFromClient = true) {
|
||||
for (boolean readAfterClose = false;; readAfterClose = true) {
|
||||
try {
|
||||
test(writeFromClient, readAfterClose);
|
||||
} catch (Failure x) {
|
||||
x.printStackTrace(log);
|
||||
failures++;
|
||||
}
|
||||
if (readAfterClose)
|
||||
break;
|
||||
}
|
||||
if (writeFromClient)
|
||||
break;
|
||||
}
|
||||
|
||||
if (failures > 0) {
|
||||
log.println();
|
||||
throw new RuntimeException("Some tests failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
119
test/jdk/java/nio/channels/SocketChannel/LingerOnClose.java
Normal file
119
test/jdk/java/nio/channels/SocketChannel/LingerOnClose.java
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 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 8203059
|
||||
* @summary Test SocketChannel.close with SO_LINGER enabled
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
public class LingerOnClose {
|
||||
|
||||
private enum TestMode {
|
||||
BLOCKING,
|
||||
NON_BLOCKING,
|
||||
NON_BLOCKING_AND_REGISTERED;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
// blocking mode
|
||||
test(TestMode.BLOCKING, -1);
|
||||
test(TestMode.BLOCKING, 0);
|
||||
test(TestMode.BLOCKING, 1);
|
||||
|
||||
// non-blocking mode
|
||||
test(TestMode.NON_BLOCKING, -1);
|
||||
test(TestMode.NON_BLOCKING, 0);
|
||||
test(TestMode.NON_BLOCKING, 1);
|
||||
|
||||
// non-blocking mode, close while registered with Selector
|
||||
test(TestMode.NON_BLOCKING_AND_REGISTERED, -1);
|
||||
test(TestMode.NON_BLOCKING_AND_REGISTERED, 0);
|
||||
test(TestMode.NON_BLOCKING_AND_REGISTERED, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test closing a SocketChannel with SO_LINGER set to the given linger
|
||||
* interval. If the linger interval is 0, it checks that the peer observes
|
||||
* a connection reset (TCP RST).
|
||||
*/
|
||||
static void test(TestMode mode, int interval) throws IOException {
|
||||
SocketChannel sc = null;
|
||||
SocketChannel peer = null;
|
||||
Selector sel = null;
|
||||
|
||||
try (ServerSocketChannel ssc = ServerSocketChannel.open()) {
|
||||
ssc.bind(new InetSocketAddress(InetAddress.getLocalHost(), 0));
|
||||
|
||||
// establish loopback connection
|
||||
sc = SocketChannel.open(ssc.getLocalAddress());
|
||||
peer = ssc.accept();
|
||||
|
||||
// configured blocking mode and register with Selector if needed
|
||||
if (mode != TestMode.BLOCKING)
|
||||
sc.configureBlocking(false);
|
||||
if (mode == TestMode.NON_BLOCKING_AND_REGISTERED) {
|
||||
sel = Selector.open();
|
||||
sc.register(sel, SelectionKey.OP_READ);
|
||||
sel.selectNow();
|
||||
}
|
||||
|
||||
// enable or disable SO_LINGER
|
||||
sc.setOption(StandardSocketOptions.SO_LINGER, interval);
|
||||
|
||||
// close channel and flush Selector if needed
|
||||
sc.close();
|
||||
if (mode == TestMode.NON_BLOCKING_AND_REGISTERED)
|
||||
sel.selectNow();
|
||||
|
||||
// read other end of connection, expect EOF or RST
|
||||
ByteBuffer bb = ByteBuffer.allocate(100);
|
||||
try {
|
||||
int n = peer.read(bb);
|
||||
if (interval == 0) {
|
||||
throw new RuntimeException("RST expected");
|
||||
} else if (n != -1) {
|
||||
throw new RuntimeException("EOF expected");
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
if (interval != 0) {
|
||||
// exception not expected
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (sc != null) sc.close();
|
||||
if (peer != null) peer.close();
|
||||
if (sel != null) sel.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
74
test/jdk/java/nio/channels/SocketChannel/LocalAddress.java
Normal file
74
test/jdk/java/nio/channels/SocketChannel/LocalAddress.java
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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 4672609 5076965 4739238
|
||||
* @summary Test getLocalAddress getLocalPort
|
||||
* @library .. /test/lib
|
||||
* @build jdk.test.lib.Utils TestServers
|
||||
* @run main LocalAddress
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
|
||||
public class LocalAddress {
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (TestServers.EchoServer echoServer
|
||||
= TestServers.EchoServer.startNewServer()) {
|
||||
test1(echoServer);
|
||||
}
|
||||
}
|
||||
|
||||
static void test1(TestServers.AbstractServer server) throws Exception {
|
||||
InetAddress bogus = InetAddress.getByName("0.0.0.0");
|
||||
InetSocketAddress saddr = new InetSocketAddress(
|
||||
server.getAddress(), server.getPort());
|
||||
|
||||
//Test1: connect only
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
try {
|
||||
sc.connect(saddr);
|
||||
InetAddress ia = sc.socket().getLocalAddress();
|
||||
if (ia == null || ia.equals(bogus))
|
||||
throw new RuntimeException("test failed");
|
||||
} finally {
|
||||
sc.close();
|
||||
}
|
||||
|
||||
//Test2: bind and connect
|
||||
sc = SocketChannel.open();
|
||||
try {
|
||||
sc.socket().bind(new InetSocketAddress(0));
|
||||
if (sc.socket().getLocalPort() == 0)
|
||||
throw new RuntimeException("test failed");
|
||||
sc.socket().connect(saddr);
|
||||
InetAddress ia = sc.socket().getLocalAddress();
|
||||
if (ia == null || ia.isAnyLocalAddress())
|
||||
throw new RuntimeException("test failed");
|
||||
} finally {
|
||||
sc.close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
86
test/jdk/java/nio/channels/SocketChannel/Open.java
Normal file
86
test/jdk/java/nio/channels/SocketChannel/Open.java
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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.
|
||||
*/
|
||||
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.Pipe;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
|
||||
public class Open {
|
||||
|
||||
static void test1() {
|
||||
for (int i=0; i<11000; i++) {
|
||||
try {
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
} catch (Exception e) {
|
||||
// Presumably "Too many open files"
|
||||
}
|
||||
}
|
||||
}
|
||||
static void test2() {
|
||||
for (int i=0; i<11000; i++) {
|
||||
try {
|
||||
DatagramChannel sc = DatagramChannel.open();
|
||||
} catch (Exception e) {
|
||||
// Presumably "Too many open files"
|
||||
}
|
||||
}
|
||||
}
|
||||
static void test3() {
|
||||
SelectorProvider sp = SelectorProvider.provider();
|
||||
for (int i=0; i<11000; i++) {
|
||||
try {
|
||||
Pipe p = sp.openPipe();
|
||||
} catch (Exception e) {
|
||||
// Presumably "Too many open files"
|
||||
}
|
||||
}
|
||||
}
|
||||
static void test4() {
|
||||
for (int i=0; i<11000; i++) {
|
||||
try {
|
||||
ServerSocketChannel sc = ServerSocketChannel.open();
|
||||
} catch (Exception e) {
|
||||
// Presumably "Too many open files"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Load necessary classes ahead of time
|
||||
DatagramChannel dc = DatagramChannel.open();
|
||||
Exception se = new SocketException();
|
||||
SelectorProvider sp = SelectorProvider.provider();
|
||||
Pipe p = sp.openPipe();
|
||||
ServerSocketChannel ssc = ServerSocketChannel.open();
|
||||
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
}
|
||||
|
||||
}
|
||||
134
test/jdk/java/nio/channels/SocketChannel/OpenLeak.java
Normal file
134
test/jdk/java/nio/channels/SocketChannel/OpenLeak.java
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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 6548464
|
||||
* @summary SocketChannel.open(SocketAddress) leaks file descriptor if
|
||||
* connection cannot be established
|
||||
* @requires vm.flagless
|
||||
* @build OpenLeak
|
||||
* @run junit/othervm/timeout=480 OpenLeak
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.UnresolvedAddressException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
|
||||
public class OpenLeak {
|
||||
|
||||
static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.ROOT);
|
||||
static final boolean IS_WINDOWS_2016 = OS_NAME.contains("windows") && OS_NAME.contains("2016");
|
||||
|
||||
// On Windows Server 2016 trying to connect to port 47 consumes the
|
||||
// whole connect timeout - which makes the test fail in timeout.
|
||||
// We skip this part of the test on Windows Server 2016
|
||||
static final boolean TEST_WITH_RESERVED_PORT = !IS_WINDOWS_2016;
|
||||
|
||||
private static final int MAX_LOOP = 250000;
|
||||
|
||||
|
||||
// Try to find a suitable port to provoke a "Connection Refused"
|
||||
// error.
|
||||
private static InetSocketAddress findSuitableRefusedAddress(InetSocketAddress isa)
|
||||
throws IOException {
|
||||
if (!TEST_WITH_RESERVED_PORT) return null;
|
||||
var addr = isa.getAddress();
|
||||
try (SocketChannel sc1 = SocketChannel.open(isa)) {
|
||||
// If we manage to connect, let's try to use some other
|
||||
// port.
|
||||
// port 51 is reserved too - there should be nothing there...
|
||||
isa = new InetSocketAddress(addr, 51);
|
||||
try (SocketChannel sc2 = SocketChannel.open(isa)) {
|
||||
}
|
||||
// OK, last attempt...
|
||||
// port 61 is reserved too - there should be nothing there...
|
||||
isa = new InetSocketAddress(addr, 61);
|
||||
try (SocketChannel sc3 = SocketChannel.open(isa)) {
|
||||
}
|
||||
System.err.println("Could not find a suitable port");
|
||||
return null;
|
||||
} catch (ConnectException x) {
|
||||
}
|
||||
return isa;
|
||||
}
|
||||
|
||||
private static InetSocketAddress createUnresolved(InetSocketAddress isa, InetSocketAddress def) {
|
||||
var sa = isa == null ? def : isa;
|
||||
return InetSocketAddress.createUnresolved(sa.getHostString(), sa.getPort());
|
||||
}
|
||||
|
||||
|
||||
// Builds a list of test cases
|
||||
static List<Object[]> testCases() throws Exception {
|
||||
InetAddress lo = InetAddress.getLoopbackAddress();
|
||||
|
||||
// Try to find a suitable port that will cause a
|
||||
// Connection Refused exception
|
||||
// port 47 is reserved - there should be nothing there...
|
||||
InetSocketAddress def = new InetSocketAddress(lo, 47);
|
||||
InetSocketAddress isa = findSuitableRefusedAddress(def);
|
||||
InetSocketAddress sa = createUnresolved(isa, def);
|
||||
|
||||
final List<Object[]> cases = new ArrayList<>();
|
||||
cases.add(new Object[]{sa, UnresolvedAddressException.class});
|
||||
if (isa != null) {
|
||||
cases.add(new Object[]{isa, ConnectException.class});
|
||||
}
|
||||
return cases;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("testCases")
|
||||
public void test(SocketAddress sa, Class<? extends Throwable> expectedException) throws Exception {
|
||||
System.err.printf("%nExpecting %s for %s%n", expectedException, sa);
|
||||
|
||||
int i = 0;
|
||||
try {
|
||||
for (i = 0; i < MAX_LOOP; i++) {
|
||||
Throwable x =
|
||||
assertThrows(expectedException, () -> SocketChannel.open(sa));
|
||||
if (i < 5 || i >= MAX_LOOP - 5) {
|
||||
// print a message for the first five and last 5 exceptions
|
||||
System.err.println(x);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
System.err.println("Failed at " + i + " with " + t);
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
177
test/jdk/java/nio/channels/SocketChannel/OutOfBand.java
Normal file
177
test/jdk/java/nio/channels/SocketChannel/OutOfBand.java
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 2015, 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 socket adapter sendUrgentData method
|
||||
* @bug 6963907
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
|
||||
public class OutOfBand {
|
||||
|
||||
private static final Random rand = new Random();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ServerSocketChannel ssc = null;
|
||||
SocketChannel sc1 = null;
|
||||
SocketChannel sc2 = null;
|
||||
|
||||
try {
|
||||
|
||||
// establish loopback connection
|
||||
ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
SocketAddress remote =
|
||||
new InetSocketAddress(lh, ssc.socket().getLocalPort());
|
||||
sc1 = SocketChannel.open(remote);
|
||||
sc2 = ssc.accept();
|
||||
|
||||
// enable SO_OOBLINE on server side
|
||||
sc2.socket().setOOBInline(true);
|
||||
|
||||
// run tests
|
||||
test1(sc1, sc2);
|
||||
test2(sc1, sc2);
|
||||
test3(sc1, sc2);
|
||||
} finally {
|
||||
if (sc1 != null) sc1.close();
|
||||
if (sc2 != null) sc2.close();
|
||||
if (ssc != null) ssc.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test to check that OOB/TCP urgent byte is received.
|
||||
*/
|
||||
static void test1(SocketChannel client, SocketChannel server)
|
||||
throws Exception
|
||||
{
|
||||
assert server.socket().getOOBInline();
|
||||
ByteBuffer bb = ByteBuffer.allocate(100);
|
||||
for (int i=0; i<1000; i++) {
|
||||
int b1 = -127 + rand.nextInt(384);
|
||||
client.socket().sendUrgentData(b1);
|
||||
|
||||
bb.clear();
|
||||
if (server.read(bb) != 1)
|
||||
throw new RuntimeException("One byte expected");
|
||||
bb.flip();
|
||||
byte b2 = bb.get();
|
||||
if ((byte)b1 != b2)
|
||||
throw new RuntimeException("Unexpected byte");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test to check that OOB/TCP urgent byte is received, maybe with
|
||||
* OOB mark changing.
|
||||
*/
|
||||
static void test2(final SocketChannel client, SocketChannel server)
|
||||
throws Exception
|
||||
{
|
||||
assert server.socket().getOOBInline();
|
||||
Runnable sender = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
for (int i=0; i<256; i++)
|
||||
client.socket().sendUrgentData(i);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
Thread thr = new Thread(sender);
|
||||
thr.start();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(256);
|
||||
while (bb.hasRemaining()) {
|
||||
if (server.read(bb) < 0)
|
||||
throw new RuntimeException("Unexpected EOF");
|
||||
}
|
||||
bb.flip();
|
||||
byte expect = 0;
|
||||
while (bb.hasRemaining()) {
|
||||
if (bb.get() != expect)
|
||||
throw new RuntimeException("Unexpected byte");
|
||||
expect++;
|
||||
}
|
||||
|
||||
thr.join();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that is close to some real world examples where an urgent byte is
|
||||
* used to "cancel" a long running query or transaction on the server.
|
||||
*/
|
||||
static void test3(SocketChannel client, final SocketChannel server)
|
||||
throws Exception
|
||||
{
|
||||
final int STOP = rand.nextInt(256);
|
||||
|
||||
assert server.socket().getOOBInline();
|
||||
Runnable reader = new Runnable() {
|
||||
public void run() {
|
||||
ByteBuffer bb = ByteBuffer.allocate(100);
|
||||
try {
|
||||
int n = server.read(bb);
|
||||
if (n != 1) {
|
||||
String msg = (n < 0) ? "Unexpected EOF" :
|
||||
"One byte expected";
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
bb.flip();
|
||||
if (bb.get() != (byte)STOP)
|
||||
throw new RuntimeException("Unexpected byte");
|
||||
bb.flip();
|
||||
server.write(bb);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Thread thr = new Thread(reader);
|
||||
thr.start();
|
||||
|
||||
// "stop" server
|
||||
client.socket().sendUrgentData(STOP);
|
||||
|
||||
// wait for server reply
|
||||
ByteBuffer bb = ByteBuffer.allocate(100);
|
||||
int n = client.read(bb);
|
||||
if (n != 1)
|
||||
throw new RuntimeException("Unexpected number of bytes");
|
||||
bb.flip();
|
||||
if (bb.get() != (byte)STOP)
|
||||
throw new RuntimeException("Unexpected reply");
|
||||
|
||||
thr.join();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* 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 8358764
|
||||
* @summary Test closing a socket while a thread is blocked in read. The connection
|
||||
* should be closed gracefuly so that the peer reads EOF.
|
||||
* @run junit PeerReadsAfterAsyncClose
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class PeerReadsAfterAsyncClose {
|
||||
|
||||
static Stream<ThreadFactory> factories() {
|
||||
return Stream.of(Thread.ofPlatform().factory(), Thread.ofVirtual().factory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Close SocketChannel while a thread is blocked reading from the channel's socket.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("factories")
|
||||
void testCloseDuringSocketChannelRead(ThreadFactory factory) throws Exception {
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
try (var listener = new ServerSocket()) {
|
||||
listener.bind(new InetSocketAddress(loopback, 0));
|
||||
|
||||
try (SocketChannel sc = SocketChannel.open(listener.getLocalSocketAddress());
|
||||
Socket peer = listener.accept()) {
|
||||
|
||||
// start thread to read from channel
|
||||
var cceThrown = new AtomicBoolean();
|
||||
Thread thread = factory.newThread(() -> {
|
||||
try {
|
||||
sc.read(ByteBuffer.allocate(1));
|
||||
fail();
|
||||
} catch (ClosedChannelException e) {
|
||||
cceThrown.set(true);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
try {
|
||||
// close SocketChannel when thread sampled in implRead
|
||||
onReach(thread, "sun.nio.ch.SocketChannelImpl.implRead", () -> {
|
||||
try {
|
||||
sc.close();
|
||||
} catch (IOException ignore) { }
|
||||
});
|
||||
|
||||
// peer should read EOF
|
||||
int n = peer.getInputStream().read();
|
||||
assertEquals(-1, n);
|
||||
} finally {
|
||||
thread.join();
|
||||
}
|
||||
assertEquals(true, cceThrown.get(), "ClosedChannelException not thrown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Socket while a thread is blocked reading from the socket.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("factories")
|
||||
void testCloseDuringSocketUntimedRead(ThreadFactory factory) throws Exception {
|
||||
testCloseDuringSocketRead(factory, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Socket while a thread is blocked reading from the socket with a timeout.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("factories")
|
||||
void testCloseDuringSockeTimedRead(ThreadFactory factory) throws Exception {
|
||||
testCloseDuringSocketRead(factory, 60_000);
|
||||
}
|
||||
|
||||
private void testCloseDuringSocketRead(ThreadFactory factory, int timeout) throws Exception {
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
try (var listener = new ServerSocket()) {
|
||||
listener.bind(new InetSocketAddress(loopback, 0));
|
||||
|
||||
try (Socket s = new Socket(loopback, listener.getLocalPort());
|
||||
Socket peer = listener.accept()) {
|
||||
|
||||
// start thread to read from socket
|
||||
var seThrown = new AtomicBoolean();
|
||||
Thread thread = factory.newThread(() -> {
|
||||
try {
|
||||
s.setSoTimeout(timeout);
|
||||
s.getInputStream().read();
|
||||
fail();
|
||||
} catch (SocketException e) {
|
||||
seThrown.set(true);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
try {
|
||||
// close Socket when thread sampled in implRead
|
||||
onReach(thread, "sun.nio.ch.NioSocketImpl.implRead", () -> {
|
||||
try {
|
||||
s.close();
|
||||
} catch (IOException ignore) { }
|
||||
});
|
||||
|
||||
// peer should read EOF
|
||||
int n = peer.getInputStream().read();
|
||||
assertEquals(-1, n);
|
||||
} finally {
|
||||
thread.join();
|
||||
}
|
||||
assertEquals(true, seThrown.get(), "SocketException not thrown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given action when the given target thread is sampled at the given
|
||||
* location. The location takes the form "{@code c.m}" where
|
||||
* {@code c} is the fully qualified class name and {@code m} is the method name.
|
||||
*/
|
||||
private void onReach(Thread target, String location, Runnable action) {
|
||||
int index = location.lastIndexOf('.');
|
||||
String className = location.substring(0, index);
|
||||
String methodName = location.substring(index + 1);
|
||||
Thread.ofPlatform().daemon(true).start(() -> {
|
||||
try {
|
||||
boolean found = false;
|
||||
while (!found) {
|
||||
found = contains(target.getStackTrace(), className, methodName);
|
||||
if (!found) {
|
||||
Thread.sleep(20);
|
||||
}
|
||||
}
|
||||
action.run();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given stack trace contains an element for the given class
|
||||
* and method name.
|
||||
*/
|
||||
private boolean contains(StackTraceElement[] stack, String className, String methodName) {
|
||||
return Arrays.stream(stack)
|
||||
.anyMatch(e -> className.equals(e.getClassName())
|
||||
&& methodName.equals(e.getMethodName()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8246707
|
||||
* @library /test/lib
|
||||
* @summary Reading or Writing to a closed SocketChannel should throw a ClosedChannelException
|
||||
* @run testng/othervm ReadWriteAfterClose
|
||||
*/
|
||||
|
||||
public class ReadWriteAfterClose {
|
||||
|
||||
private ServerSocketChannel listener;
|
||||
private SocketAddress saddr;
|
||||
private static final int bufCapacity = 4;
|
||||
private static final int bufArraySize = 4;
|
||||
private static final Class<ClosedChannelException> CCE = ClosedChannelException.class;
|
||||
|
||||
@BeforeTest
|
||||
public void setUp() throws IOException {
|
||||
listener = ServerSocketChannel.open();
|
||||
listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
|
||||
saddr = listener.getLocalAddress();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteAfterClose1() throws IOException {
|
||||
SocketChannel sc = SocketChannel.open(saddr);
|
||||
sc.close();
|
||||
ByteBuffer bufWrite = ByteBuffer.allocate(bufCapacity);
|
||||
Throwable ex = expectThrows(CCE, () -> sc.write(bufWrite));
|
||||
assertEquals(ex.getClass(), CCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteAfterClose2() throws IOException {
|
||||
SocketChannel sc = SocketChannel.open(saddr);
|
||||
sc.close();
|
||||
ByteBuffer[] bufArrayWrite = allocateBufArray();
|
||||
Throwable ex = expectThrows(CCE, () -> sc.write(bufArrayWrite));
|
||||
assertEquals(ex.getClass(), CCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteAfterClose3() throws IOException {
|
||||
SocketChannel sc = SocketChannel.open(saddr);
|
||||
sc.close();
|
||||
ByteBuffer[] bufArrayWrite = allocateBufArray();
|
||||
Throwable ex = expectThrows(CCE, () -> sc.write(bufArrayWrite, 0, bufArraySize));
|
||||
assertEquals(ex.getClass(), CCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadAfterClose1() throws IOException {
|
||||
SocketChannel sc = SocketChannel.open(saddr);
|
||||
sc.close();
|
||||
ByteBuffer dst = ByteBuffer.allocate(bufCapacity);
|
||||
Throwable ex = expectThrows(CCE, () -> sc.read(dst));
|
||||
assertEquals(ex.getClass(), CCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadAfterClose2() throws IOException {
|
||||
SocketChannel sc = SocketChannel.open(saddr);
|
||||
sc.close();
|
||||
ByteBuffer[] dstArray = allocateBufArray();
|
||||
Throwable ex = expectThrows(CCE, () -> sc.read(dstArray));
|
||||
assertEquals(ex.getClass(), CCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadAfterClose3() throws IOException {
|
||||
SocketChannel sc = SocketChannel.open(saddr);
|
||||
sc.close();
|
||||
ByteBuffer[] dstArray = allocateBufArray();
|
||||
Throwable ex = expectThrows(CCE, () -> sc.read(dstArray, 0, bufArraySize));
|
||||
assertEquals(ex.getClass(), CCE);
|
||||
}
|
||||
|
||||
public ByteBuffer[] allocateBufArray() {
|
||||
ByteBuffer[] bufArr = new ByteBuffer[bufArraySize];
|
||||
for (int i = 0; i < bufArraySize; i++)
|
||||
bufArr[i] = ByteBuffer.allocate(bufCapacity);
|
||||
return bufArr;
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void tearDown() throws IOException {
|
||||
listener.close();
|
||||
}
|
||||
}
|
||||
205
test/jdk/java/nio/channels/SocketChannel/SendUrgentData.java
Normal file
205
test/jdk/java/nio/channels/SocketChannel/SendUrgentData.java
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8071599
|
||||
* @run main/othervm SendUrgentData
|
||||
* @run main/othervm SendUrgentData -inline
|
||||
* @summary Test sending of urgent data.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
public class SendUrgentData {
|
||||
|
||||
/**
|
||||
* The arguments may be one of the following:
|
||||
* <ol>
|
||||
* <li>-server</li>
|
||||
* <li>-client host port [-inline]</li>
|
||||
* <li>[-inline]</li>
|
||||
* </ol>
|
||||
* The first option creates a standalone server, the second a standalone
|
||||
* client, and the third a self-contained server-client pair on the
|
||||
* local host.
|
||||
*
|
||||
* @param args
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
ServerSocketChannelThread serverThread
|
||||
= new ServerSocketChannelThread("SendUrgentDataServer");
|
||||
serverThread.start();
|
||||
boolean b = serverThread.isAlive();
|
||||
|
||||
String host = null;
|
||||
int port = 0;
|
||||
boolean inline = false;
|
||||
if (args.length > 0 && args[0].equals("-server")) {
|
||||
System.out.println(serverThread.getAddress());
|
||||
while (true) {
|
||||
Thread.sleep(60_000);
|
||||
}
|
||||
} else {
|
||||
if (args.length > 0 && args[0].equals("-client")) {
|
||||
host = args[1];
|
||||
port = Integer.parseInt(args[2]);
|
||||
if (args.length > 3) {
|
||||
inline = args[2].equals("-inline");
|
||||
}
|
||||
} else {
|
||||
host = "localhost";
|
||||
port = serverThread.getAddress().getPort();
|
||||
if (args.length > 0) {
|
||||
inline = args[0].equals("-inline");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OOB Inline : "+inline);
|
||||
|
||||
SocketAddress sa = new InetSocketAddress(host, port);
|
||||
|
||||
try (SocketChannel sc = SocketChannel.open(sa)) {
|
||||
sc.configureBlocking(false);
|
||||
sc.socket().setOOBInline(inline);
|
||||
|
||||
sc.socket().sendUrgentData(0);
|
||||
System.out.println("wrote 1 OOB byte");
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(new byte[100 * 1000]);
|
||||
|
||||
int blocked = 0;
|
||||
long total = 0;
|
||||
|
||||
int n;
|
||||
do {
|
||||
n = sc.write(bb);
|
||||
if (n == 0) {
|
||||
System.out.println("blocked, wrote " + total + " so far");
|
||||
if (++blocked == 10) {
|
||||
break;
|
||||
}
|
||||
Thread.sleep(100);
|
||||
} else {
|
||||
total += n;
|
||||
bb.rewind();
|
||||
}
|
||||
} while (n > 0);
|
||||
|
||||
long attempted = 0;
|
||||
while (attempted < total) {
|
||||
bb.rewind();
|
||||
n = sc.write(bb);
|
||||
System.out.println("wrote " + n + " normal bytes");
|
||||
attempted += bb.capacity();
|
||||
|
||||
String osName = System.getProperty("os.name").toLowerCase();
|
||||
|
||||
try {
|
||||
sc.socket().sendUrgentData(0);
|
||||
} catch (IOException ex) {
|
||||
if (osName.contains("linux")) {
|
||||
if (!ex.getMessage().contains("Socket buffer full")) {
|
||||
throw new RuntimeException("Unexpected message", ex);
|
||||
}
|
||||
} else if (osName.contains("os x") || osName.contains("mac")) {
|
||||
if (!ex.getMessage().equals("No buffer space available")) {
|
||||
throw new RuntimeException("Unexpected message", ex);
|
||||
}
|
||||
} else if (osName.contains("windows")) {
|
||||
if (!ex.getMessage().equals("Socket buffer full")) {
|
||||
throw new RuntimeException("Unexpected message", ex);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected IOException", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ex) {
|
||||
// don't want to fail on this so just print trace and break
|
||||
ex.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
serverThread.close();
|
||||
}
|
||||
}
|
||||
|
||||
static class ServerSocketChannelThread extends Thread {
|
||||
|
||||
private ServerSocketChannel ssc;
|
||||
|
||||
private ServerSocketChannelThread(String name) {
|
||||
super(name);
|
||||
try {
|
||||
ssc = ServerSocketChannel.open();
|
||||
ssc.bind(new InetSocketAddress((0)));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (ssc.isOpen()) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
try {
|
||||
ssc.close();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
System.out.println("ServerSocketChannelThread exiting ...");
|
||||
}
|
||||
|
||||
public InetSocketAddress getAddress() throws IOException {
|
||||
if (ssc == null) {
|
||||
throw new IllegalStateException("ServerSocketChannel not created");
|
||||
}
|
||||
|
||||
return (InetSocketAddress) ssc.getLocalAddress();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
ssc.close();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
210
test/jdk/java/nio/channels/SocketChannel/ShortWrite.java
Normal file
210
test/jdk/java/nio/channels/SocketChannel/ShortWrite.java
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 7176630 7074436
|
||||
* @summary Check for short writes on SocketChannels configured in blocking mode
|
||||
* @key randomness
|
||||
* @requires test.thread.factory != "Virtual"
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.Random;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
public class ShortWrite {
|
||||
|
||||
static final Random rand = new Random();
|
||||
|
||||
/**
|
||||
* Returns a checksum on the remaining bytes in the given buffers.
|
||||
*/
|
||||
static long computeChecksum(ByteBuffer... bufs) {
|
||||
CRC32 crc32 = new CRC32();
|
||||
for (int i=0; i<bufs.length; i++)
|
||||
crc32.update(bufs[i]);
|
||||
return crc32.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* A task that reads the expected number of bytes and returns the CRC32
|
||||
* of those bytes.
|
||||
*/
|
||||
static class Reader implements Callable<Long> {
|
||||
final SocketChannel sc;
|
||||
final ByteBuffer buf;
|
||||
|
||||
Reader(SocketChannel sc, int expectedSize) {
|
||||
this.sc = sc;
|
||||
this.buf = ByteBuffer.allocate(expectedSize);
|
||||
}
|
||||
|
||||
public Long call() throws Exception {
|
||||
while (buf.hasRemaining()) {
|
||||
int n = sc.read(buf);
|
||||
if (n == -1)
|
||||
throw new RuntimeException("Premature EOF encountered");
|
||||
}
|
||||
buf.flip();
|
||||
return computeChecksum(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exercise write(ByteBuffer) with given number of bytes.
|
||||
*/
|
||||
static void test1(ExecutorService pool,
|
||||
SocketChannel source,
|
||||
SocketChannel sink,
|
||||
int size)
|
||||
throws Exception
|
||||
{
|
||||
System.out.println("write(ByteBuffer), size=" + size);
|
||||
|
||||
// random bytes in the buffer
|
||||
ByteBuffer buf = ByteBuffer.allocate(size);
|
||||
rand.nextBytes(buf.array());
|
||||
|
||||
// submit task to read the bytes
|
||||
Future<Long> result = pool.submit(new Reader(sink, size));
|
||||
|
||||
// write the bytes
|
||||
int n = source.write(buf);
|
||||
if (n != size)
|
||||
throw new RuntimeException("Short write detected");
|
||||
|
||||
// check the bytes that were received match
|
||||
buf.rewind();
|
||||
long expected = computeChecksum(buf);
|
||||
long actual = result.get();
|
||||
if (actual != expected)
|
||||
throw new RuntimeException("Checksum did not match");
|
||||
}
|
||||
|
||||
/**
|
||||
* Exercise write(ByteBuffer[]) with buffers of the given sizes.
|
||||
*/
|
||||
static void testN(ExecutorService pool,
|
||||
SocketChannel source,
|
||||
SocketChannel sink,
|
||||
int... sizes)
|
||||
throws Exception
|
||||
{
|
||||
System.out.print("write(ByteBuffer[]), sizes=");
|
||||
for (int size: sizes)
|
||||
System.out.print(size + " ");
|
||||
System.out.println();
|
||||
|
||||
int total = 0;
|
||||
int len = sizes.length;
|
||||
ByteBuffer[] bufs = new ByteBuffer[len];
|
||||
for (int i=0; i<len; i++) {
|
||||
int size = sizes[i];
|
||||
ByteBuffer buf = ByteBuffer.allocate(size);
|
||||
rand.nextBytes(buf.array());
|
||||
bufs[i] = buf;
|
||||
total += size;
|
||||
}
|
||||
|
||||
// submit task to read the bytes
|
||||
Future<Long> result = pool.submit(new Reader(sink, total));
|
||||
|
||||
// write the bytes
|
||||
long n = source.write(bufs);
|
||||
if (n != total)
|
||||
throw new RuntimeException("Short write detected");
|
||||
|
||||
// check the bytes that were received match
|
||||
for (int i=0; i<len; i++)
|
||||
bufs[i].rewind();
|
||||
long expected = computeChecksum(bufs);
|
||||
long actual = result.get();
|
||||
if (actual != expected)
|
||||
throw new RuntimeException("Checksum did not match");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ExecutorService pool = Executors.newSingleThreadExecutor();
|
||||
try {
|
||||
try (ServerSocketChannel ssc = ServerSocketChannel.open()) {
|
||||
ssc.bind(new InetSocketAddress(0));
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
int port = ssc.socket().getLocalPort();
|
||||
SocketAddress sa = new InetSocketAddress(lh, port);
|
||||
|
||||
try (SocketChannel source = SocketChannel.open(sa);
|
||||
SocketChannel sink = ssc.accept())
|
||||
{
|
||||
// Exercise write(BufferBuffer) on sizes around 128k
|
||||
int BOUNDARY = 128 * 1024;
|
||||
for (int size=(BOUNDARY-2); size<=(BOUNDARY+2); size++) {
|
||||
test1(pool, source, sink, size);
|
||||
}
|
||||
|
||||
// Exercise write(BufferBuffer) on random sizes
|
||||
for (int i=0; i<20; i++) {
|
||||
int size = rand.nextInt(1024*1024);
|
||||
test1(pool, source, sink, size);
|
||||
}
|
||||
|
||||
// Exercise write(BufferBuffer[]) on sizes around 128k
|
||||
for (int i=BOUNDARY-2; i<=BOUNDARY+2; i++) {
|
||||
testN(pool, source, sink, i);
|
||||
testN(pool, source, sink, 0, i);
|
||||
testN(pool, source, sink, i, 0);
|
||||
for (int j=BOUNDARY-2; j<=BOUNDARY+2; j++) {
|
||||
testN(pool, source, sink, i, j);
|
||||
testN(pool, source, sink, 0, i, j);
|
||||
testN(pool, source, sink, i, 0, j);
|
||||
testN(pool, source, sink, i, j, 0);
|
||||
for (int k=BOUNDARY-2; k<=BOUNDARY+2; k++) {
|
||||
testN(pool, source, sink, i, j, k);
|
||||
testN(pool, source, sink, 0, i, j, k);
|
||||
testN(pool, source, sink, i, 0, j, k);
|
||||
testN(pool, source, sink, i, j, 0, k);
|
||||
testN(pool, source, sink, i, j, k, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Exercise write(BufferBuffer[]) on random sizes
|
||||
// (assumes IOV_MAX >= 8)
|
||||
for (int i=0; i<20; i++) {
|
||||
int n = rand.nextInt(9);
|
||||
int[] sizes = new int[n];
|
||||
for (int j=0; j<n; j++) {
|
||||
sizes[j] = rand.nextInt(1024*1024);
|
||||
}
|
||||
testN(pool, source, sink, sizes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
pool.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
86
test/jdk/java/nio/channels/SocketChannel/Shutdown.java
Normal file
86
test/jdk/java/nio/channels/SocketChannel/Shutdown.java
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2011, 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 4618960 4516760
|
||||
* @summary Test shutdownXXX and isInputShutdown
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
|
||||
public class Shutdown {
|
||||
|
||||
/**
|
||||
* Accept a connection, and close it immediately causing a hard reset.
|
||||
*/
|
||||
static void acceptAndReset(ServerSocketChannel ssc) throws IOException {
|
||||
SocketChannel peer = ssc.accept();
|
||||
try {
|
||||
peer.setOption(StandardSocketOptions.SO_LINGER, 0);
|
||||
peer.configureBlocking(false);
|
||||
peer.write(ByteBuffer.wrap(new byte[128*1024]));
|
||||
} finally {
|
||||
peer.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ServerSocketChannel ssc = ServerSocketChannel.open()
|
||||
.bind(new InetSocketAddress(0));
|
||||
try {
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort();
|
||||
SocketAddress remote = new InetSocketAddress(lh, port);
|
||||
|
||||
// Test SocketChannel shutdownXXX
|
||||
SocketChannel sc;
|
||||
sc = SocketChannel.open(remote);
|
||||
try {
|
||||
acceptAndReset(ssc);
|
||||
sc.shutdownInput();
|
||||
sc.shutdownOutput();
|
||||
} finally {
|
||||
sc.close();
|
||||
}
|
||||
|
||||
// Test Socket adapter shutdownXXX and isShutdownInput
|
||||
sc = SocketChannel.open(remote);
|
||||
try {
|
||||
acceptAndReset(ssc);
|
||||
boolean before = sc.socket().isInputShutdown();
|
||||
sc.socket().shutdownInput();
|
||||
boolean after = sc.socket().isInputShutdown();
|
||||
if (before || !after)
|
||||
throw new RuntimeException("Before and after test failed");
|
||||
sc.socket().shutdownOutput();
|
||||
} finally {
|
||||
sc.close();
|
||||
}
|
||||
} finally {
|
||||
ssc.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
150
test/jdk/java/nio/channels/SocketChannel/SocketInheritance.java
Normal file
150
test/jdk/java/nio/channels/SocketChannel/SocketInheritance.java
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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 Sockets shouldn't be inherited when creating a child process
|
||||
* @requires (os.family == "windows")
|
||||
*/
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
|
||||
public class SocketInheritance {
|
||||
|
||||
/*
|
||||
* Simple helper class to direct process output to the parent
|
||||
* System.out
|
||||
*/
|
||||
static class IOHandler implements Runnable {
|
||||
InputStream in;
|
||||
|
||||
IOHandler(InputStream in) {
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
static void handle(InputStream in) {
|
||||
IOHandler handler = new IOHandler(in);
|
||||
Thread thr = new Thread(handler);
|
||||
thr.setDaemon(true);
|
||||
thr.start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
byte b[] = new byte[100];
|
||||
for (;;) {
|
||||
int n = in.read(b);
|
||||
if (n < 0) return;
|
||||
System.out.write(b, 0, n);
|
||||
}
|
||||
} catch (IOException ioe) { }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// connect to the given port
|
||||
static SocketChannel connect(int port) throws IOException {
|
||||
InetAddress lh = InetAddress.getLoopbackAddress();
|
||||
InetSocketAddress isa = new InetSocketAddress(lh, port);
|
||||
return SocketChannel.open(isa);
|
||||
}
|
||||
|
||||
// simple child process that handshakes with the parent and then
|
||||
// waits indefinitely until it is destroyed
|
||||
static void child(int port) {
|
||||
try {
|
||||
connect(port).close();
|
||||
} catch (IOException x) {
|
||||
x.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
try {
|
||||
Thread.sleep(10*1000);
|
||||
} catch (InterruptedException x) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Creates a loopback connection.
|
||||
// Forks process which should not inherit the sockets.
|
||||
// Close the sockets, and attempt to re-bind the listener.
|
||||
|
||||
static void start() throws Exception {
|
||||
|
||||
// setup loopback connection
|
||||
ServerSocketChannel ssc = ServerSocketChannel.open();
|
||||
ssc.socket().bind( new InetSocketAddress(0) );
|
||||
|
||||
int port = ssc.socket().getLocalPort();
|
||||
|
||||
SocketChannel sc1 = connect(port);
|
||||
SocketChannel sc2 = ssc.accept();
|
||||
|
||||
// launch the child
|
||||
String cmd = System.getProperty("java.home") + File.separator + "bin" +
|
||||
File.separator + "java";
|
||||
String testClasses = System.getProperty("test.classes");
|
||||
if (testClasses != null)
|
||||
cmd += " -cp " + testClasses;
|
||||
cmd += " SocketInheritance -child " + port;
|
||||
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
|
||||
IOHandler.handle(p.getInputStream());
|
||||
IOHandler.handle(p.getErrorStream());
|
||||
|
||||
// wait for child to connect
|
||||
SocketChannel sc3 = ssc.accept();
|
||||
|
||||
// close sockets
|
||||
sc1.close();
|
||||
sc2.close();
|
||||
sc3.close();
|
||||
ssc.close();
|
||||
|
||||
// re-bind the listener - if the sockets were inherited then
|
||||
// this will fail
|
||||
try {
|
||||
ssc = ServerSocketChannel.open();
|
||||
ssc.socket().bind(new InetSocketAddress(port));
|
||||
ssc.close();
|
||||
} finally {
|
||||
p.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 0) {
|
||||
start();
|
||||
} else {
|
||||
if (args[0].equals("-child")) {
|
||||
child(Integer.parseInt(args[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
165
test/jdk/java/nio/channels/SocketChannel/SocketOptionTests.java
Normal file
165
test/jdk/java/nio/channels/SocketChannel/SocketOptionTests.java
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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 4640544 8044773
|
||||
* @summary Unit test to check SocketChannel setOption/getOption/options
|
||||
* methods.
|
||||
* @modules java.base/sun.net.ext
|
||||
* jdk.net
|
||||
* @requires !vm.graal.enabled
|
||||
* @run main SocketOptionTests
|
||||
* @run main/othervm --limit-modules=java.base SocketOptionTests
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Set;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
import static java.net.StandardSocketOptions.*;
|
||||
import static jdk.net.ExtendedSocketOptions.*;
|
||||
|
||||
public class SocketOptionTests {
|
||||
|
||||
static void checkOption(SocketChannel sc, SocketOption name, Object expectedValue)
|
||||
throws IOException
|
||||
{
|
||||
Object value = sc.getOption(name);
|
||||
if (!value.equals(expectedValue))
|
||||
throw new RuntimeException("value not as expected");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
try (var channel = SocketChannel.open()) {
|
||||
test(channel);
|
||||
}
|
||||
}
|
||||
|
||||
static void test(SocketChannel sc) throws IOException {
|
||||
Set<SocketOption<?>> extendedOptions = ExtendedSocketOptions.clientSocketOptions();
|
||||
Set<SocketOption<?>> keepAliveOptions = Set.of(TCP_KEEPCOUNT, TCP_KEEPIDLE, TCP_KEEPINTERVAL);
|
||||
boolean keepAliveOptionsSupported = extendedOptions.containsAll(keepAliveOptions);
|
||||
Set<SocketOption<?>> expected;
|
||||
if (keepAliveOptionsSupported) {
|
||||
expected = Set.of(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE,
|
||||
SO_REUSEADDR, SO_LINGER, TCP_NODELAY, TCP_KEEPCOUNT,
|
||||
TCP_KEEPIDLE, TCP_KEEPINTERVAL);
|
||||
} else {
|
||||
expected = Set.of(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE,
|
||||
SO_REUSEADDR, SO_LINGER, TCP_NODELAY);
|
||||
}
|
||||
for (SocketOption opt: expected) {
|
||||
if (!sc.supportedOptions().contains(opt))
|
||||
throw new RuntimeException(opt.name() + " should be supported");
|
||||
}
|
||||
|
||||
// check specified defaults
|
||||
int linger = sc.<Integer>getOption(SO_LINGER);
|
||||
if (linger >= 0)
|
||||
throw new RuntimeException("initial value of SO_LINGER should be < 0");
|
||||
checkOption(sc, SO_KEEPALIVE, false);
|
||||
checkOption(sc, TCP_NODELAY, false);
|
||||
|
||||
// allowed to change when not bound
|
||||
sc.setOption(SO_KEEPALIVE, true);
|
||||
checkOption(sc, SO_KEEPALIVE, true);
|
||||
sc.setOption(SO_KEEPALIVE, false);
|
||||
checkOption(sc, SO_KEEPALIVE, false);
|
||||
sc.setOption(SO_SNDBUF, 128*1024); // can't check
|
||||
sc.setOption(SO_RCVBUF, 256*1024); // can't check
|
||||
int before, after;
|
||||
before = sc.getOption(SO_SNDBUF);
|
||||
after = sc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
|
||||
if (after < before)
|
||||
throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
|
||||
before = sc.getOption(SO_RCVBUF);
|
||||
after = sc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
|
||||
if (after < before)
|
||||
throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
|
||||
sc.setOption(SO_REUSEADDR, true);
|
||||
checkOption(sc, SO_REUSEADDR, true);
|
||||
sc.setOption(SO_REUSEADDR, false);
|
||||
checkOption(sc, SO_REUSEADDR, false);
|
||||
sc.setOption(SO_LINGER, 10);
|
||||
linger = sc.<Integer>getOption(SO_LINGER);
|
||||
if (linger < 1)
|
||||
throw new RuntimeException("expected linger to be enabled");
|
||||
sc.setOption(SO_LINGER, -1);
|
||||
linger = sc.<Integer>getOption(SO_LINGER);
|
||||
if (linger >= 0)
|
||||
throw new RuntimeException("expected linger to be disabled");
|
||||
sc.setOption(TCP_NODELAY, true);
|
||||
checkOption(sc, TCP_NODELAY, true);
|
||||
sc.setOption(TCP_NODELAY, false); // can't check
|
||||
|
||||
// bind socket
|
||||
sc.bind(new InetSocketAddress(0));
|
||||
|
||||
// allow to change when bound
|
||||
sc.setOption(SO_KEEPALIVE, true);
|
||||
checkOption(sc, SO_KEEPALIVE, true);
|
||||
sc.setOption(SO_KEEPALIVE, false);
|
||||
checkOption(sc, SO_KEEPALIVE, false);
|
||||
|
||||
sc.setOption(SO_LINGER, 10);
|
||||
linger = sc.<Integer>getOption(SO_LINGER);
|
||||
if (linger < 1)
|
||||
throw new RuntimeException("expected linger to be enabled");
|
||||
sc.setOption(SO_LINGER, -1);
|
||||
linger = sc.<Integer>getOption(SO_LINGER);
|
||||
if (linger >= 0)
|
||||
throw new RuntimeException("expected linger to be disabled");
|
||||
sc.setOption(TCP_NODELAY, true); // can't check
|
||||
sc.setOption(TCP_NODELAY, false); // can't check
|
||||
if (keepAliveOptionsSupported) {
|
||||
sc.setOption(TCP_KEEPIDLE, 1234);
|
||||
checkOption(sc, TCP_KEEPIDLE, 1234);
|
||||
sc.setOption(TCP_KEEPINTERVAL, 123);
|
||||
checkOption(sc, TCP_KEEPINTERVAL, 123);
|
||||
sc.setOption(TCP_KEEPCOUNT, 7);
|
||||
checkOption(sc, TCP_KEEPCOUNT, 7);
|
||||
}
|
||||
// NullPointerException
|
||||
try {
|
||||
sc.setOption(null, "value");
|
||||
throw new RuntimeException("NullPointerException not thrown");
|
||||
} catch (NullPointerException x) {
|
||||
}
|
||||
try {
|
||||
sc.getOption(null);
|
||||
throw new RuntimeException("NullPointerException not thrown");
|
||||
} catch (NullPointerException x) {
|
||||
}
|
||||
|
||||
// ClosedChannelException
|
||||
sc.close();
|
||||
try {
|
||||
sc.setOption(TCP_NODELAY, true);
|
||||
throw new RuntimeException("ClosedChannelException not thrown");
|
||||
} catch (ClosedChannelException x) {
|
||||
}
|
||||
}
|
||||
}
|
||||
59
test/jdk/java/nio/channels/SocketChannel/Trivial.java
Normal file
59
test/jdk/java/nio/channels/SocketChannel/Trivial.java
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 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
|
||||
* @summary Test trivial stuff
|
||||
*/
|
||||
|
||||
import java.nio.channels.*;
|
||||
|
||||
|
||||
public class Trivial {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
Selector sel = Selector.open();
|
||||
try {
|
||||
if (sc.keyFor(sel) != null)
|
||||
throw new Exception("keyFor != null");
|
||||
sc.configureBlocking(false);
|
||||
SelectionKey sk = sc.register(sel, SelectionKey.OP_READ, args);
|
||||
if (sc.keyFor(sel) != sk)
|
||||
throw new Exception("keyFor returned " + sc.keyFor(sel));
|
||||
if (sk.attachment() != args)
|
||||
throw new Exception("attachment() returned " + sk.attachment());
|
||||
Trivial t = new Trivial();
|
||||
sk.attach(t);
|
||||
if (sk.attachment() != t)
|
||||
throw new Exception("Wrong attachment");
|
||||
sk.isReadable();
|
||||
sk.isWritable();
|
||||
sk.isConnectable();
|
||||
sk.isAcceptable();
|
||||
} finally {
|
||||
sel.close();
|
||||
sc.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
107
test/jdk/java/nio/channels/SocketChannel/UnboundSocketTests.java
Normal file
107
test/jdk/java/nio/channels/SocketChannel/UnboundSocketTests.java
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 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 6442073
|
||||
* @summary Check getXXX methods for local/remote port/address/socketaddress
|
||||
* match socket spec for unbound case
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
|
||||
public class UnboundSocketTests {
|
||||
|
||||
static int failures = 0;
|
||||
|
||||
static void check(String msg, Object actual, Object expected) {
|
||||
System.out.format("%s expected: %s, actual: %s", msg, expected, actual);
|
||||
if (actual == expected) {
|
||||
System.out.println(" [PASS]");
|
||||
} else {
|
||||
System.out.println(" [FAIL]");
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
|
||||
static void checkIsAnyLocalAddress(String msg, InetAddress actual) {
|
||||
System.out.format("%s actual: %s", msg, actual);
|
||||
if (actual.isAnyLocalAddress()) {
|
||||
System.out.println(" [PASS]");
|
||||
} else {
|
||||
System.out.println(" [FAIL]");
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("\n-- SocketChannel --");
|
||||
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
try {
|
||||
check("getLocalPort()", sc.socket().getLocalPort(), -1);
|
||||
checkIsAnyLocalAddress("getLocalAddress()",
|
||||
sc.socket().getLocalAddress());
|
||||
check("getLocalSocketAddress()", sc.socket().getLocalSocketAddress(), null);
|
||||
|
||||
check("getPort()", sc.socket().getPort(), 0);
|
||||
check("getInetAddress()", sc.socket().getInetAddress(), null);
|
||||
check("getRemoteSocketAddress()", sc.socket().getRemoteSocketAddress(), null);
|
||||
} finally {
|
||||
sc.close();
|
||||
}
|
||||
|
||||
System.out.println("\n-- ServerSocketChannel --");
|
||||
|
||||
ServerSocketChannel ssc = ServerSocketChannel.open();
|
||||
try {
|
||||
check("getLocalPort()", ssc.socket().getLocalPort(), -1);
|
||||
check("getInetAddress()", ssc.socket().getInetAddress(), null);
|
||||
check("getLocalSocketAddress()", ssc.socket().getLocalSocketAddress(), null);
|
||||
} finally {
|
||||
ssc.close();
|
||||
}
|
||||
|
||||
System.out.println("\n-- DatagramChannel --");
|
||||
|
||||
DatagramChannel dc = DatagramChannel.open();
|
||||
try {
|
||||
// not specified
|
||||
check("getLocalPort()", dc.socket().getLocalPort(), 0);
|
||||
|
||||
checkIsAnyLocalAddress("getLocalAddress()",
|
||||
dc.socket().getLocalAddress());
|
||||
check("getLocalSocketAddress()", dc.socket().getLocalSocketAddress(), null);
|
||||
|
||||
check("getPort()", dc.socket().getPort(), -1);
|
||||
check("getInetAddress()", dc.socket().getInetAddress(), null);
|
||||
check("getRemoteSocketAddress()", dc.socket().getRemoteSocketAddress(), null);
|
||||
} finally {
|
||||
dc.close();
|
||||
}
|
||||
|
||||
if (failures > 0) {
|
||||
throw new RuntimeException(failures + " sub-tests(s) failed.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
221
test/jdk/java/nio/channels/SocketChannel/VectorIO.java
Normal file
221
test/jdk/java/nio/channels/SocketChannel/VectorIO.java
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 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 8191025
|
||||
* @summary Test socketchannel vector IO (use -Dseed=X to set PRNG seed)
|
||||
* @library .. /test/lib
|
||||
* @build jdk.test.lib.RandomFactory
|
||||
* @run main VectorIO
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.*;
|
||||
import jdk.test.lib.RandomFactory;
|
||||
|
||||
public class VectorIO {
|
||||
|
||||
private static Random generator = RandomFactory.getRandom();
|
||||
|
||||
static int testSize;
|
||||
|
||||
// whether to use the write/read variant with a length parameter
|
||||
static boolean setLength;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
testSize = 1;
|
||||
setLength = false;
|
||||
runTest();
|
||||
for(int i=15; i<18; i++) {
|
||||
testSize = i;
|
||||
setLength = !setLength;
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
static void runTest() throws Exception {
|
||||
System.err.println("Length " + testSize);
|
||||
Server sv = new Server(testSize);
|
||||
sv.start();
|
||||
bufferTest(sv.port());
|
||||
if (sv.finish(8000) == 0)
|
||||
throw new Exception("Failed: Length = " + testSize);
|
||||
}
|
||||
|
||||
static void bufferTest(int port) throws Exception {
|
||||
ByteBuffer[] bufs = new ByteBuffer[testSize];
|
||||
long total = 0L;
|
||||
for(int i=0; i<testSize; i++) {
|
||||
String source = "buffer" + i;
|
||||
if (generator.nextBoolean())
|
||||
bufs[i] = ByteBuffer.allocateDirect(source.length());
|
||||
else
|
||||
bufs[i] = ByteBuffer.allocate(source.length());
|
||||
|
||||
bufs[i].put(source.getBytes("8859_1"));
|
||||
bufs[i].flip();
|
||||
total += bufs[i].remaining();
|
||||
}
|
||||
|
||||
ByteBuffer[] bufsPlus1 = new ByteBuffer[bufs.length + 1];
|
||||
System.arraycopy(bufs, 0, bufsPlus1, 0, bufs.length);
|
||||
|
||||
// Get a connection to the server
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
InetSocketAddress isa = new InetSocketAddress(lh, port);
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
sc.connect(isa);
|
||||
sc.configureBlocking(generator.nextBoolean());
|
||||
|
||||
// Write the data out
|
||||
long rem = total;
|
||||
while (rem > 0L) {
|
||||
long bytesWritten;
|
||||
if (setLength) {
|
||||
bytesWritten = sc.write(bufsPlus1, 0, bufs.length);
|
||||
} else {
|
||||
bytesWritten = sc.write(bufs);
|
||||
}
|
||||
if (bytesWritten == 0) {
|
||||
if (sc.isBlocking()) {
|
||||
throw new RuntimeException("write did not block");
|
||||
} else {
|
||||
System.err.println("Non-blocking write() wrote zero bytes");
|
||||
}
|
||||
Thread.sleep(50);
|
||||
} else {
|
||||
rem -= bytesWritten;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
sc.close();
|
||||
}
|
||||
|
||||
static class Server
|
||||
extends TestThread
|
||||
{
|
||||
final int testSize;
|
||||
final ServerSocketChannel ssc;
|
||||
|
||||
Server(int testSize) throws IOException {
|
||||
super("Server " + testSize);
|
||||
this.testSize = testSize;
|
||||
this.ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
|
||||
}
|
||||
|
||||
int port() {
|
||||
return ssc.socket().getLocalPort();
|
||||
}
|
||||
|
||||
void go() throws Exception {
|
||||
bufferTest();
|
||||
}
|
||||
|
||||
void bufferTest() throws Exception {
|
||||
long total = 0L;
|
||||
ByteBuffer[] bufs = new ByteBuffer[testSize];
|
||||
for(int i=0; i<testSize; i++) {
|
||||
String source = "buffer" + i;
|
||||
if (generator.nextBoolean())
|
||||
bufs[i] = ByteBuffer.allocateDirect(source.length());
|
||||
else
|
||||
bufs[i] = ByteBuffer.allocate(source.length());
|
||||
total += bufs[i].capacity();
|
||||
}
|
||||
|
||||
ByteBuffer[] bufsPlus1 = new ByteBuffer[bufs.length + 1];
|
||||
System.arraycopy(bufs, 0, bufsPlus1, 0, bufs.length);
|
||||
|
||||
// Get a connection from client
|
||||
SocketChannel sc = null;
|
||||
|
||||
try {
|
||||
|
||||
ssc.configureBlocking(false);
|
||||
|
||||
for (;;) {
|
||||
sc = ssc.accept();
|
||||
if (sc != null) {
|
||||
System.err.println("accept() succeeded");
|
||||
break;
|
||||
}
|
||||
Thread.sleep(50);
|
||||
}
|
||||
|
||||
sc.configureBlocking(generator.nextBoolean());
|
||||
|
||||
// Read data into multiple buffers
|
||||
long avail = total;
|
||||
while (avail > 0) {
|
||||
long bytesRead;
|
||||
if (setLength) {
|
||||
bytesRead = sc.read(bufsPlus1, 0, bufs.length);
|
||||
} else {
|
||||
bytesRead = sc.read(bufs);
|
||||
}
|
||||
if (bytesRead < 0)
|
||||
break;
|
||||
if (bytesRead == 0) {
|
||||
if (sc.isBlocking()) {
|
||||
throw new RuntimeException("read did not block");
|
||||
} else {
|
||||
System.err.println
|
||||
("Non-blocking read() read zero bytes");
|
||||
}
|
||||
Thread.sleep(50);
|
||||
}
|
||||
avail -= bytesRead;
|
||||
}
|
||||
|
||||
// Check results
|
||||
for(int i=0; i<testSize; i++) {
|
||||
String expected = "buffer" + i;
|
||||
bufs[i].flip();
|
||||
int size = bufs[i].capacity();
|
||||
byte[] data = new byte[size];
|
||||
for(int j=0; j<size; j++)
|
||||
data[j] = bufs[i].get();
|
||||
String message = new String(data, "8859_1");
|
||||
if (!message.equals(expected))
|
||||
throw new Exception("Wrong data: Got "
|
||||
+ message + ", expected "
|
||||
+ expected);
|
||||
}
|
||||
|
||||
} finally {
|
||||
// Clean up
|
||||
ssc.close();
|
||||
if (sc != null)
|
||||
sc.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
151
test/jdk/java/nio/channels/SocketChannel/VectorParams.java
Normal file
151
test/jdk/java/nio/channels/SocketChannel/VectorParams.java
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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 4865031
|
||||
* @summary Test ScatteringByteChannel/GatheringByteChannel read/write
|
||||
* @library .. /test/lib
|
||||
* @build jdk.test.lib.Utils TestServers
|
||||
* @run main VectorParams
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
|
||||
public class VectorParams {
|
||||
|
||||
static java.io.PrintStream out = System.out;
|
||||
|
||||
static final int testSize = 10;
|
||||
static ByteBuffer[] bufs = null;
|
||||
static InetSocketAddress isa = null;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (TestServers.DayTimeServer daytimeServer
|
||||
= TestServers.DayTimeServer.startNewServer(100)) {
|
||||
initBufs(daytimeServer);
|
||||
testSocketChannelVectorParams();
|
||||
testDatagramChannelVectorParams();
|
||||
testPipeVectorParams();
|
||||
testFileVectorParams();
|
||||
}
|
||||
}
|
||||
|
||||
static void initBufs(TestServers.DayTimeServer daytimeServer) throws Exception {
|
||||
bufs = new ByteBuffer[testSize];
|
||||
for(int i=0; i<testSize; i++) {
|
||||
String source = "buffer" + i;
|
||||
bufs[i] = ByteBuffer.allocate(source.length());
|
||||
bufs[i].put(source.getBytes("8859_1"));
|
||||
bufs[i].flip();
|
||||
}
|
||||
isa = new InetSocketAddress(daytimeServer.getAddress(),
|
||||
daytimeServer.getPort());
|
||||
}
|
||||
|
||||
static void testSocketChannelVectorParams() throws Exception {
|
||||
SocketChannel sc = SocketChannel.open(isa);
|
||||
tryBadWrite(sc, bufs, 0, -1);
|
||||
tryBadWrite(sc, bufs, -1, 0);
|
||||
tryBadWrite(sc, bufs, 0, 1000);
|
||||
tryBadWrite(sc, bufs, 1000, 1);
|
||||
tryBadRead(sc, bufs, 0, -1);
|
||||
tryBadRead(sc, bufs, -1, 0);
|
||||
tryBadRead(sc, bufs, 0, 1000);
|
||||
tryBadRead(sc, bufs, 1000, 1);
|
||||
sc.close();
|
||||
}
|
||||
|
||||
static void testDatagramChannelVectorParams() throws Exception {
|
||||
DatagramChannel dc = DatagramChannel.open();
|
||||
dc.connect(isa);
|
||||
tryBadRead(dc, bufs, 0, -1);
|
||||
tryBadRead(dc, bufs, -1, 0);
|
||||
tryBadRead(dc, bufs, 0, 1000);
|
||||
tryBadRead(dc, bufs, 1000, 1);
|
||||
tryBadWrite(dc, bufs, 0, -1);
|
||||
tryBadWrite(dc, bufs, -1, 0);
|
||||
tryBadWrite(dc, bufs, 0, 1000);
|
||||
tryBadWrite(dc, bufs, 1000, 1);
|
||||
dc.close();
|
||||
}
|
||||
|
||||
static void testPipeVectorParams() throws Exception {
|
||||
Pipe p = Pipe.open();
|
||||
Pipe.SinkChannel sink = p.sink();
|
||||
Pipe.SourceChannel source = p.source();
|
||||
tryBadWrite(sink, bufs, 0, -1);
|
||||
tryBadWrite(sink, bufs, -1, 0);
|
||||
tryBadWrite(sink, bufs, 0, 1000);
|
||||
tryBadWrite(sink, bufs, 1000, 1);
|
||||
tryBadRead(source, bufs, 0, -1);
|
||||
tryBadRead(source, bufs, -1, 0);
|
||||
tryBadRead(source, bufs, 0, 1000);
|
||||
tryBadRead(source, bufs, 1000, 1);
|
||||
sink.close();
|
||||
source.close();
|
||||
}
|
||||
|
||||
static void testFileVectorParams() throws Exception {
|
||||
File testFile = File.createTempFile("filevec", null);
|
||||
testFile.deleteOnExit();
|
||||
RandomAccessFile raf = new RandomAccessFile(testFile, "rw");
|
||||
FileChannel fc = raf.getChannel();
|
||||
tryBadWrite(fc, bufs, 0, -1);
|
||||
tryBadWrite(fc, bufs, -1, 0);
|
||||
tryBadWrite(fc, bufs, 0, 1000);
|
||||
tryBadWrite(fc, bufs, 1000, 1);
|
||||
tryBadRead(fc, bufs, 0, -1);
|
||||
tryBadRead(fc, bufs, -1, 0);
|
||||
tryBadRead(fc, bufs, 0, 1000);
|
||||
tryBadRead(fc, bufs, 1000, 1);
|
||||
fc.close();
|
||||
}
|
||||
|
||||
private static void tryBadWrite(GatheringByteChannel gbc,
|
||||
ByteBuffer[] bufs, int offset, int len)
|
||||
throws Exception
|
||||
{
|
||||
try {
|
||||
gbc.write(bufs, offset, len);
|
||||
throw new RuntimeException("Expected exception not thrown");
|
||||
} catch (IndexOutOfBoundsException ioobe) {
|
||||
// Correct result
|
||||
}
|
||||
}
|
||||
|
||||
private static void tryBadRead(ScatteringByteChannel sbc,
|
||||
ByteBuffer[] bufs, int offset, int len)
|
||||
throws Exception
|
||||
{
|
||||
try {
|
||||
sbc.read(bufs, offset, len);
|
||||
throw new RuntimeException("Expected exception not thrown");
|
||||
} catch (IndexOutOfBoundsException ioobe) {
|
||||
// Correct result
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
132
test/jdk/java/nio/channels/SocketChannel/Write.java
Normal file
132
test/jdk/java/nio/channels/SocketChannel/Write.java
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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 4854354
|
||||
* @summary Test vector write faster than can be read
|
||||
* @library ..
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class Write {
|
||||
|
||||
static Random generator = new Random();
|
||||
|
||||
static int testSize = 15;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
WriteServer sv = new WriteServer();
|
||||
sv.start();
|
||||
bufferTest(sv.port());
|
||||
if (sv.finish(8000) == 0)
|
||||
throw new Exception("Failed" );
|
||||
}
|
||||
|
||||
static void bufferTest(int port) throws Exception {
|
||||
ByteBuffer[] bufs = new ByteBuffer[testSize];
|
||||
for(int i=0; i<testSize; i++) {
|
||||
String source =
|
||||
"a muchmuchmuchmuchmuchmuchmuchmuch larger buffer numbered " +
|
||||
i;
|
||||
bufs[i] = ByteBuffer.allocateDirect(source.length());
|
||||
}
|
||||
|
||||
// Get a connection to the server
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
InetSocketAddress isa = new InetSocketAddress(lh, port);
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
sc.connect(isa);
|
||||
sc.configureBlocking(false);
|
||||
|
||||
// Try to overflow the socket buffer
|
||||
long total = 0;
|
||||
for (int i=0; i<100; i++) {
|
||||
long bytesWritten = sc.write(bufs);
|
||||
if (bytesWritten > 0)
|
||||
total += bytesWritten;
|
||||
for(int j=0; j<testSize; j++)
|
||||
bufs[j].rewind();
|
||||
}
|
||||
|
||||
// Clean up
|
||||
sc.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class WriteServer extends TestThread {
|
||||
|
||||
static Random generator = new Random();
|
||||
|
||||
|
||||
final ServerSocketChannel ssc;
|
||||
|
||||
WriteServer() throws IOException {
|
||||
super("WriteServer");
|
||||
this.ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
|
||||
}
|
||||
|
||||
int port() {
|
||||
return ssc.socket().getLocalPort();
|
||||
}
|
||||
|
||||
void go() throws Exception {
|
||||
bufferTest();
|
||||
}
|
||||
|
||||
void bufferTest() throws Exception {
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(5);
|
||||
|
||||
// Get a connection from client
|
||||
SocketChannel sc = null;
|
||||
|
||||
try {
|
||||
ssc.configureBlocking(false);
|
||||
|
||||
for (;;) {
|
||||
sc = ssc.accept();
|
||||
if (sc != null)
|
||||
break;
|
||||
Thread.sleep(50);
|
||||
}
|
||||
|
||||
// I'm a slow reader...
|
||||
Thread.sleep(3000);
|
||||
|
||||
} finally {
|
||||
// Clean up
|
||||
ssc.close();
|
||||
if (sc != null)
|
||||
sc.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue