提交 a680b522 编写于 作者: A alanb

6963907: (so) Socket adapter need to implement sendUrgentData

Reviewed-by: chegar
上级 9e96e77b
...@@ -119,6 +119,7 @@ SUNWprivate_1.1 { ...@@ -119,6 +119,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_ServerSocketChannelImpl_accept0; Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs; Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_SocketChannelImpl_checkConnect; Java_sun_nio_ch_SocketChannelImpl_checkConnect;
Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect; Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
......
...@@ -106,6 +106,7 @@ SUNWprivate_1.1 { ...@@ -106,6 +106,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_ServerSocketChannelImpl_accept0; Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs; Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_SocketChannelImpl_checkConnect; Java_sun_nio_ch_SocketChannelImpl_checkConnect;
Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect; Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
......
...@@ -336,7 +336,12 @@ public class SocketAdaptor ...@@ -336,7 +336,12 @@ public class SocketAdaptor
} }
public void sendUrgentData(int data) throws IOException { public void sendUrgentData(int data) throws IOException {
throw new SocketException("Urgent data not supported"); synchronized (sc.blockingLock()) {
if (!sc.isBlocking())
throw new IllegalBlockingModeException();
int n = sc.sendOutOfBandData((byte)data);
assert n == 1;
}
} }
public void setOOBInline(boolean on) throws SocketException { public void setOOBInline(boolean on) throws SocketException {
......
...@@ -498,6 +498,36 @@ class SocketChannelImpl ...@@ -498,6 +498,36 @@ class SocketChannelImpl
return write0(Util.subsequence(srcs, offset, length)); return write0(Util.subsequence(srcs, offset, length));
} }
// package-private
int sendOutOfBandData(byte b) throws IOException {
synchronized (writeLock) {
ensureWriteOpen();
int n = 0;
try {
begin();
synchronized (stateLock) {
if (!isOpen())
return 0;
writerThread = NativeThread.current();
}
for (;;) {
n = sendOutOfBandData(fd, b);
if ((n == IOStatus.INTERRUPTED) && isOpen())
continue;
return IOStatus.normalize(n);
}
} finally {
writerCleanup();
end((n > 0) || (n == IOStatus.UNAVAILABLE));
synchronized (stateLock) {
if ((n <= 0) && (!isOutputOpen))
throw new AsynchronousCloseException();
}
assert IOStatus.check(n);
}
}
}
protected void implConfigureBlocking(boolean block) throws IOException { protected void implConfigureBlocking(boolean block) throws IOException {
IOUtil.configureBlocking(fd, block); IOUtil.configureBlocking(fd, block);
} }
...@@ -957,6 +987,9 @@ class SocketChannelImpl ...@@ -957,6 +987,9 @@ class SocketChannelImpl
boolean block, boolean ready) boolean block, boolean ready)
throws IOException; throws IOException;
private static native int sendOutOfBandData(FileDescriptor fd, byte data)
throws IOException;
static { static {
Util.load(); Util.load();
nd = new SocketDispatcher(); nd = new SocketDispatcher();
......
...@@ -84,3 +84,11 @@ Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this, ...@@ -84,3 +84,11 @@ Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this,
} }
return 0; return 0;
} }
JNIEXPORT jint JNICALL
Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData(JNIEnv* env, jclass this,
jobject fdo, jbyte b)
{
int n = send(fdval(env, fdo), (const void*)&b, 1, MSG_OOB);
return convertReturnVal(env, n, JNI_FALSE);
}
...@@ -139,3 +139,16 @@ Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this, ...@@ -139,3 +139,16 @@ Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this,
return 0; return 0;
} }
JNIEXPORT jint JNICALL
Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData(JNIEnv* env, jclass this,
jobject fdo, jbyte b)
{
int n = send(fdval(env, fdo), (const char*)&b, 1, MSG_OOB);
if (n == SOCKET_ERROR) {
handleSocketError(env, WSAGetLastError());
return IOS_THROWN;
} else {
return n;
}
}
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
* @summary Test socket adapter sendUrgentData method
* @bug 6963907
*/
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);
test4(sc1);
} 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();
}
static void test4(SocketChannel sc) throws IOException {
boolean blocking = sc.isBlocking();
sc.configureBlocking(false);
try {
sc.socket().sendUrgentData(0);
throw new RuntimeException("IllegalBlockingModeException expected");
} catch (IllegalBlockingModeException x) {
// expected
} finally {
sc.configureBlocking(blocking);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册