diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index 2e5d37bb1a..9a7656db91 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -279,7 +279,7 @@ doListen(JNIEnv* e, int s, sockaddr_in* address) } } -bool +void doFinishConnect(JNIEnv* e, int socket) { int error; @@ -289,12 +289,9 @@ doFinishConnect(JNIEnv* e, int socket) if (r != 0 or size != sizeof(int)) { throwIOException(e); - } else if (einProgress(error)) { - return false; - } else if (error != 0) { + } else if (error and not einProgress(error)) { throwIOException(e, socketErrorString(e, error)); } - return true; } bool @@ -426,12 +423,12 @@ Java_java_nio_channels_SocketChannel_natDoConnect(JNIEnv *e, return s; } -extern "C" JNIEXPORT jboolean JNICALL +extern "C" JNIEXPORT void JNICALL Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv *e, jclass, jint socket) { - return doFinishConnect(e, socket); + doFinishConnect(e, socket); } extern "C" JNIEXPORT jint JNICALL diff --git a/classpath/java/nio/channels/GatheringByteChannel.java b/classpath/java/nio/channels/GatheringByteChannel.java new file mode 100644 index 0000000000..5696f5e980 --- /dev/null +++ b/classpath/java/nio/channels/GatheringByteChannel.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2011, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public interface GatheringByteChannel extends WritableByteChannel { + public long write(ByteBuffer[] srcs) throws IOException; + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException; +} diff --git a/classpath/java/nio/channels/SelectableChannel.java b/classpath/java/nio/channels/SelectableChannel.java index a8dc302dc7..734bce9fc8 100644 --- a/classpath/java/nio/channels/SelectableChannel.java +++ b/classpath/java/nio/channels/SelectableChannel.java @@ -19,6 +19,8 @@ public abstract class SelectableChannel implements Channel { abstract int socketFD(); + abstract void handleReadyOps(int ops); + public abstract SelectableChannel configureBlocking(boolean v) throws IOException; diff --git a/classpath/java/nio/channels/SocketChannel.java b/classpath/java/nio/channels/SocketChannel.java index 4dbc352558..d0296f4833 100644 --- a/classpath/java/nio/channels/SocketChannel.java +++ b/classpath/java/nio/channels/SocketChannel.java @@ -18,12 +18,13 @@ import java.net.Socket; import java.nio.ByteBuffer; public class SocketChannel extends SelectableChannel - implements ReadableByteChannel, WritableByteChannel + implements ReadableByteChannel, GatheringByteChannel { public static final int InvalidSocket = -1; int socket = InvalidSocket; boolean connected = false; + boolean readyToConnect = false; boolean blocking = true; public static SocketChannel open() throws IOException { @@ -66,8 +67,18 @@ public class SocketChannel extends SelectableChannel public boolean finishConnect() throws IOException { if (! connected) { - connected = natFinishConnect(socket); + while (blocking && ! readyToConnect) { + Selector selector = Selector.open(); + SelectionKey key = register(selector, SelectionKey.OP_CONNECT, null); + + selector.select(); + } + + natFinishConnect(socket); + + connected = readyToConnect; } + return connected; } @@ -117,6 +128,23 @@ public class SocketChannel extends SelectableChannel return w; } + public long write(ByteBuffer[] srcs) throws IOException { + return write(srcs, 0, srcs.length); + } + + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException + { + long total = 0; + for (int i = offset; i < offset + length; ++i) { + total += write(srcs[i]); + if (srcs[i].hasRemaining()) { + return total; + } + } + return total; + } + private void closeSocket() { natCloseSocket(socket); } @@ -125,6 +153,12 @@ public class SocketChannel extends SelectableChannel return socket; } + void handleReadyOps(int ops) { + if ((ops & SelectionKey.OP_CONNECT) != 0) { + readyToConnect = true; + } + } + public class Handle extends Socket { public void setTcpNoDelay(boolean on) throws SocketException { natSetTcpNoDelay(socket, on); @@ -139,7 +173,7 @@ public class SocketChannel extends SelectableChannel private static native int natDoConnect(String host, int port, boolean blocking, boolean[] connected) throws IOException; - private static native boolean natFinishConnect(int socket) + private static native void natFinishConnect(int socket) throws IOException; private static native int natRead(int socket, byte[] buffer, int offset, int length, boolean blocking) throws IOException; diff --git a/classpath/java/nio/channels/SocketSelector.java b/classpath/java/nio/channels/SocketSelector.java index 27daf2670b..2482d0f180 100644 --- a/classpath/java/nio/channels/SocketSelector.java +++ b/classpath/java/nio/channels/SocketSelector.java @@ -96,6 +96,7 @@ class SocketSelector extends Selector { int ready = natUpdateReadySet(socket, key.interestOps(), state); key.readyOps(ready); if (ready != 0) { + c.handleReadyOps(ready); selectedKeys.add(key); } }