diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index 6c3fb14ee5..899982a472 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -154,17 +154,19 @@ eagain() } bool -makeNonblocking(JNIEnv* e, int d) +setBlocking(JNIEnv* e, int d, bool blocking) { #ifdef WIN32 - u_long a = 1; + u_long a = (blocking ? 0 : 1); int r = ioctlsocket(d, FIONBIO, &a); if (r != 0) { throwIOException(e); return false; } #else - int r = fcntl(d, F_SETFL, fcntl(d, F_GETFL) | O_NONBLOCK); + int r = fcntl(d, F_SETFL, (blocking + ? (fcntl(d, F_GETFL) & (~O_NONBLOCK)) + : (fcntl(d, F_GETFL) | O_NONBLOCK))); if (r < 0) { throwIOException(e); return false; @@ -231,7 +233,6 @@ doAccept(JNIEnv* e, int s) socklen_t length = sizeof(address); int r = ::accept(s, &address, &length); if (r >= 0) { - makeNonblocking(e, r); return r; } else { throwIOException(e); @@ -260,7 +261,7 @@ doWrite(int fd, const void* buffer, size_t count) } int -makeSocket(JNIEnv* e, bool blocking = false) +makeSocket(JNIEnv* e) { #ifdef WIN32 static bool wsaInitialized = false; @@ -279,8 +280,6 @@ makeSocket(JNIEnv* e, bool blocking = false) return s; } - if (not blocking) makeNonblocking(e, s); - return s; } @@ -311,6 +310,15 @@ Java_java_nio_channels_ServerSocketChannel_natDoListen(JNIEnv *e, return s; } +extern "C" JNIEXPORT void JNICALL +Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv *e, + jclass, + jint socket, + jboolean blocking) +{ + setBlocking(e, socket, blocking); +} + extern "C" JNIEXPORT void JNICALL Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv *e, jclass, @@ -325,11 +333,14 @@ Java_java_nio_channels_SocketChannel_natDoConnect(JNIEnv *e, jclass, jstring host, jint port, + jboolean blocking, jbooleanArray retVal) { int s = makeSocket(e); if (e->ExceptionOccurred()) return 0; + setBlocking(e, s, blocking); + sockaddr_in address; init(e, &address, host, port); if (e->ExceptionOccurred()) return 0; @@ -425,7 +436,8 @@ class Pipe { address.sin_family = AF_INET; address.sin_port = 0; address.sin_addr.s_addr = inet_addr("127.0.0.1"); //INADDR_LOOPBACK; - listener_ = makeSocket(e, false); + listener_ = makeSocket(e); + setBlocking(e, listener_, false); ::doListen(e, listener_, &address); socklen_t length = sizeof(sockaddr_in); @@ -435,7 +447,8 @@ class Pipe { throwIOException(e); } - writer_ = makeSocket(e, true); + writer_ = makeSocket(e); + setBlocking(e, writer_, true); connected_ = ::doConnect(e, writer_, &address); } @@ -485,8 +498,8 @@ class Pipe { return; } - if (makeNonblocking(e, pipe[0])) { - makeNonblocking(e, pipe[1]); + if (setBlocking(e, pipe[0], false)) { + setBlocking(e, pipe[1], false); } } diff --git a/classpath/java/nio/channels/ServerSocketChannel.java b/classpath/java/nio/channels/ServerSocketChannel.java index f84c9626bc..5ddbdc0f16 100644 --- a/classpath/java/nio/channels/ServerSocketChannel.java +++ b/classpath/java/nio/channels/ServerSocketChannel.java @@ -23,7 +23,7 @@ public class ServerSocketChannel extends SelectableChannel { return new ServerSocketChannel(); } - public SelectableChannel configureBlocking(boolean v) { + public SelectableChannel configureBlocking(boolean v) throws IOException { return channel.configureBlocking(v); } @@ -61,6 +61,7 @@ public class ServerSocketChannel extends SelectableChannel { throw new IllegalArgumentException(); } channel.socket = doListen(a.getHostName(), a.getPort()); + channel.configureBlocking(channel.isBlocking()); } } diff --git a/classpath/java/nio/channels/SocketChannel.java b/classpath/java/nio/channels/SocketChannel.java index 33ac011005..c6879d3a8a 100644 --- a/classpath/java/nio/channels/SocketChannel.java +++ b/classpath/java/nio/channels/SocketChannel.java @@ -24,21 +24,29 @@ public class SocketChannel extends SelectableChannel int socket = InvalidSocket; boolean connected = false; + boolean blocking = true; public static SocketChannel open() { return new SocketChannel(); } - public SelectableChannel configureBlocking(boolean v) { - if (v) throw new IllegalArgumentException(); + public SelectableChannel configureBlocking(boolean v) throws IOException { + blocking = v; + if (socket != InvalidSocket) { + configureBlocking(socket, v); + } return this; } + public boolean isBlocking() { + return blocking; + } + public Socket socket() { return new Handle(); } - public boolean connect(SocketAddress address) throws Exception { + public boolean connect(SocketAddress address) throws IOException { InetSocketAddress a; try { a = (InetSocketAddress) address; @@ -46,6 +54,7 @@ public class SocketChannel extends SelectableChannel throw new UnsupportedAddressTypeException(); } socket = doConnect(a.getHostName(), a.getPort()); + configureBlocking(blocking); return connected; } @@ -56,11 +65,11 @@ public class SocketChannel extends SelectableChannel } } - private int doConnect(String host, int port) throws Exception { + private int doConnect(String host, int port) throws IOException { if (host == null) throw new NullPointerException(); boolean b[] = new boolean[1]; - int s = natDoConnect(host, port, b); + int s = natDoConnect(host, port, blocking, b); connected = b[0]; return s; } @@ -109,11 +118,14 @@ public class SocketChannel extends SelectableChannel } } + private static native void configureBlocking(int socket, boolean blocking) + throws IOException; + private static native void natSetTcpNoDelay(int socket, boolean on) throws SocketException; - private static native int natDoConnect(String host, int port, boolean[] connected) - throws Exception; + private static native int natDoConnect(String host, int port, boolean blocking, boolean[] connected) + throws IOException; private static native int natRead(int socket, byte[] buffer, int offset, int length) throws IOException; private static native int natWrite(int socket, byte[] buffer, int offset, int length)