summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog71
-rw-r--r--NEWS6
-rw-r--r--gnu/java/net/PlainDatagramSocketImpl.java57
-rw-r--r--gnu/java/net/PlainSocketImpl.java55
-rw-r--r--include/Makefile.am3
-rw-r--r--java/net/Socket.java29
-rw-r--r--native/jni/java-net/Makefile.am1
-rw-r--r--native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c135
-rw-r--r--native/jni/java-nio/gnu_java_nio_VMChannel.c96
-rw-r--r--native/jni/native-lib/cpio.c10
-rw-r--r--native/jni/native-lib/cpio.h1
-rw-r--r--vm/reference/gnu/java/net/VMPlainSocketImpl.java119
-rw-r--r--vm/reference/gnu/java/nio/VMChannel.java38
13 files changed, 520 insertions, 101 deletions
diff --git a/ChangeLog b/ChangeLog
index db5519865..7ee8890fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,76 @@
2006-10-25 Robert Schuster <robertschuster@fsfe.org>
+ * gnu/java/net/PlainDatagramSocketImpl.java:
+ (connect): Use VMChannel instance for connect call.
+ (getTimeToLive): Call VMPlainSocketImpl.getTimeToLive.
+ (setTimeToLive): Call VMPlainSocketImpl.setTimeToLive.
+ (setOption): Handle multicast options.
+ (getOption): Handle multicast options.
+ * gnu/java/net/PlainSocketImpl.java:
+ (getTimeToLive): Call VMPlainSocketImpl.getTimeToLive.
+ (setTimeToLive): Call VMPlainSocketImpl.setTimeToLive.
+ (setOption): Filter unappropriate options.
+ (getOption): Filter unappropriate options.
+ (connect): Use given SocketAddress.
+ (close): Reset address and port.
+ (getInetAddress):
+ * include/Makefile.am: Removed all occurences of
+ gnu_java_net_VMPlainDatagramSocketImpl.h.
+ * include/gnu_java_net_VMPlainDatagramSocketImpl.h: Removed.
+ * native/jni/java-net/Makefile.am: Removed
+ gnu_java_net_VMPlainDatagramSocketImpl.c from sources.
+ * native/jni/java-net/gnu_java_net_VMPlainDatagramSocketImpl.c:
+ Removed.
+ as SocketException, declare to throw SocketException.
+ * native/jni/java-nio/gnu_java_nio_VMChannel.c: Added definitions
+ for SocketException and ConnectException.
+ (Java_gnu_java_nio_VMChannel_connect): Throw SocketException instead
+ of IOException.
+ (Java_gnu_java_nio_VMChannel_connect6): Throw SocketException instead
+ of IOException.
+ (Java_gnu_java_nio_VMChannel_accept): Rewritten.
+ (JCL_thread_interrupted): New function.
+ (initIDs): Added initialisation for isThreadInterrupted method id.
+ * native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c: Added
+ CPNET_IP_TTL to java_sockopt enum.
+ (Java_gnu_java_net_VMPlainSocketImpl_setOption): Handle CPNET_IP_TTL
+ case, handle SO_LINGER case properly.
+ (Java_gnu_java_net_VMPlainSocketImpl_getOption): Handle CPNET_IP_TTL
+ case, handle SO_LINGER case properly.
+ (Java_gnu_java_net_VMPlainSocketImpl_getMulticastInterface): New
+ function.
+ (Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface): New
+ function.
+ (Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface6): New
+ function.
+ (Java_gnu_java_net_VMPlainSocketImpl_leave6): Fixed constant to be
+ IPV6_LEAVE_GROUP.
+ * vm/reference/gnu/java/net/VMPlainDatagramSocketImpl.java: Removed.
+ * vm/reference/gnu/java/nio/VMChannel.java:
+ (connect(int, byte[], int, int)): Declare to throw SocketException.
+ (connect6): Declare to throw SocketException.
+ (connect(InetSocketAddress, int)): Catch IOException and rethrow
+ (isThreadInterrupted): New method.
+ * vm/reference/gnu/java/net/VMPlainSocketImpl.java: Added CP_IP_TTL
+ field.
+ (setTimeToLive): New method.
+ (getTimeToLive): New method.
+ (setMulticastInterface(int, InetAddress)): New method.
+ (setMulticastInterface(int, int, Inet4Address): New method.
+ (setMulticastInterface6(int, int, Inet6Address): New method.
+ (setOptions): Handle SO_LINGER case.
+ (getOptions): Add missing SO_REUSEADDR case.
+ * java/net/Socket.java:
+ (Socket(InetAddress, int, InetAddress, int, boolean)): Close socket
+ when exception was thrown out of connect().
+ (setSoLinger): Replaced instantiations with valueOf calls, replaced
+ Boolean.FALSE with Integer.valueOf(-1).
+ * native/jni/native-lib/cpio.h: Added cpio_closeOnExec declaration.
+ * native/jni/native-lib/cpio.c: Added cpio_closeOnExec implementation.
+ * NEWS: Documented VM interface changes.
+
+2006-10-25 Robert Schuster <robertschuster@fsfe.org>
+
* java/net/Inet6Address.java:
(isMulticastAddress): Fixed check.
diff --git a/NEWS b/NEWS
index 6a9b54ab0..8f24e6301 100644
--- a/NEWS
+++ b/NEWS
@@ -39,11 +39,13 @@ Runtime interface changes:
* gnu.java.nio.VMPipe has been similarly changed.
* gnu.java.net.VMPlainSocketImpl has been changed to remove some
functionality now provided by VMChannel; datagram socket-specific
- methods have also been moved here, deprecating
- VMPlainDatagramSocketImpl.
+ methods have also been moved here, deprecating VMPlainDatagramSocketImpl.
+* gnu.java.net.VMPlainDatagramSocketImpl removed.
New in release 0.92 (Aug 9, 2006)
+* GConf is used as a backend for java.util.prefs. GNU Classpath
+ thanks to Mario Torre for this contribution!
* libjawtgnu.so has been renamed libjawt.so for binary compatibility.
libjawt.so should be installed in a VM-specific directory rather
than directly in /usr/lib. Proprietary VMs put their libjawt.so
diff --git a/gnu/java/net/PlainDatagramSocketImpl.java b/gnu/java/net/PlainDatagramSocketImpl.java
index be2fc796b..a84525e18 100644
--- a/gnu/java/net/PlainDatagramSocketImpl.java
+++ b/gnu/java/net/PlainDatagramSocketImpl.java
@@ -1,5 +1,5 @@
/* PlainDatagramSocketImpl.java -- Default DatagramSocket implementation
- Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,7 +42,6 @@ import gnu.java.nio.VMChannel;
import java.io.IOException;
import java.io.InterruptedIOException;
-import java.lang.reflect.Field;
import java.net.DatagramPacket;
import java.net.DatagramSocketImpl;
import java.net.InetAddress;
@@ -69,7 +68,6 @@ import java.nio.ByteBuffer;
*/
public final class PlainDatagramSocketImpl extends DatagramSocketImpl
{
-
private final VMChannel channel;
/**
@@ -171,7 +169,7 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl
*/
protected void connect(InetAddress addr, int port) throws SocketException
{
- VMPlainDatagramSocketImpl.connect(this, addr, port);
+ channel.connect(new InetSocketAddress(addr, port), 0);
}
/**
@@ -203,7 +201,7 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl
*/
protected synchronized void setTimeToLive(int ttl) throws IOException
{
- setOption(VMPlainDatagramSocketImpl.IP_TTL, new Integer(ttl));
+ impl.setTimeToLive(ttl);
}
/**
@@ -215,12 +213,7 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl
*/
protected synchronized int getTimeToLive() throws IOException
{
- Object obj = getOption(VMPlainDatagramSocketImpl.IP_TTL);
-
- if (! (obj instanceof Integer))
- throw new IOException("Internal Error");
-
- return ((Integer) obj).intValue();
+ return impl.getTimeToLive();
}
protected int getLocalPort()
@@ -318,30 +311,53 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl
/**
* Sets the value of an option on the socket
*
- * @param option_id The identifier of the option to set
- * @param val The value of the option to set
+ * @param optionId The identifier of the option to set
+ * @param value The value of the option to set
*
* @exception SocketException If an error occurs
*/
- public synchronized void setOption(int option_id, Object val)
+ public synchronized void setOption(int optionId, Object value)
throws SocketException
{
- impl.setOption(option_id, val);
+ switch (optionId)
+ {
+ case IP_MULTICAST_IF:
+ case IP_MULTICAST_IF2:
+ impl.setMulticastInterface(optionId, (InetAddress) value);
+ break;
+
+ case IP_MULTICAST_LOOP:
+ case SO_BROADCAST:
+ case SO_KEEPALIVE:
+ case SO_OOBINLINE:
+ case TCP_NODELAY:
+ case IP_TOS:
+ case SO_LINGER:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ case SO_TIMEOUT:
+ case SO_REUSEADDR:
+ impl.setOption(optionId, value);
+ return;
+
+ default:
+ throw new SocketException("cannot set option " + optionId);
+ }
}
/**
* Retrieves the value of an option on the socket
*
- * @param option_id The identifier of the option to retrieve
+ * @param optionId The identifier of the option to retrieve
*
* @return The value of the option
*
* @exception SocketException If an error occurs
*/
- public synchronized Object getOption(int option_id)
+ public synchronized Object getOption(int optionId)
throws SocketException
{
- if (option_id == SO_BINDADDR)
+ if (optionId == SO_BINDADDR)
{
try
{
@@ -361,7 +377,10 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl
throw se;
}
}
- return impl.getOption(option_id);
+ if (optionId == IP_MULTICAST_IF || optionId == IP_MULTICAST_IF2)
+ return impl.getMulticastInterface(optionId);
+
+ return impl.getOption(optionId);
}
/**
diff --git a/gnu/java/net/PlainSocketImpl.java b/gnu/java/net/PlainSocketImpl.java
index 750243d5d..64e498746 100644
--- a/gnu/java/net/PlainSocketImpl.java
+++ b/gnu/java/net/PlainSocketImpl.java
@@ -39,12 +39,9 @@ exception statement from your version. */
package gnu.java.net;
-import gnu.java.nio.SelectorProviderImpl;
import gnu.java.nio.SocketChannelImpl;
import gnu.java.nio.VMChannel;
-import gnu.java.security.action.GetSecurityPropertyAction;
-import java.io.EOFException;
import java.io.InputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
@@ -56,7 +53,6 @@ import java.net.SocketException;
import java.net.SocketImpl;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
-import java.nio.channels.SocketChannel;
/**
* Written using on-line Java Platform 1.2 API Specification, as well
@@ -148,26 +144,21 @@ public class PlainSocketImpl extends SocketImpl
{
switch (optionId)
{
- case IP_MULTICAST_IF:
- case IP_MULTICAST_IF2:
- throw new UnsupportedOperationException("FIXME");
-
+ case SO_LINGER:
case IP_MULTICAST_LOOP:
case SO_BROADCAST:
case SO_KEEPALIVE:
case SO_OOBINLINE:
case TCP_NODELAY:
case IP_TOS:
- case SO_LINGER:
case SO_RCVBUF:
case SO_SNDBUF:
case SO_TIMEOUT:
case SO_REUSEADDR:
impl.setOption(optionId, value);
return;
-
- default:
- throw new SocketException("cannot set option " + optionId);
+ default:
+ throw new SocketException("Unrecognized TCP option: " + optionId);
}
}
@@ -197,10 +188,26 @@ public class PlainSocketImpl extends SocketImpl
throw se;
}
}
- if (optionId == IP_MULTICAST_IF || optionId == IP_MULTICAST_IF2)
- throw new UnsupportedOperationException ("can't get option " +
- optionId + " yet");
- return impl.getOption(optionId);
+
+ // This filters options which are invalid for TCP.
+ switch (optionId)
+ {
+ case SO_LINGER:
+ case IP_MULTICAST_LOOP:
+ case SO_BROADCAST:
+ case SO_KEEPALIVE:
+ case SO_OOBINLINE:
+ case TCP_NODELAY:
+ case IP_TOS:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ case SO_TIMEOUT:
+ case SO_REUSEADDR:
+ return impl.getOption(optionId);
+ default:
+ throw new SocketException("Unrecognized TCP option: " + optionId);
+ }
+
}
public void shutdownInput() throws IOException
@@ -274,7 +281,10 @@ public class PlainSocketImpl extends SocketImpl
boolean connected = channel.connect(address, timeout);
if (!connected)
throw new SocketTimeoutException("connect timed out");
- InetSocketAddress addr = channel.getVMChannel().getPeerAddress();
+
+ // Using the given SocketAddress is important to preserve
+ // hostnames given by the caller.
+ InetSocketAddress addr = (InetSocketAddress) address;
this.address = addr.getAddress();
this.port = addr.getPort();
}
@@ -364,6 +374,9 @@ public class PlainSocketImpl extends SocketImpl
{
if (impl.getState().isValid())
impl.close();
+
+ address = null;
+ port = -1;
}
public void sendUrgentData(int data) throws IOException
@@ -417,11 +430,18 @@ public class PlainSocketImpl extends SocketImpl
{
if (channel == null)
return null;
+
try
{
InetSocketAddress remote = channel.getVMChannel().getPeerAddress();
if (remote == null)
return null;
+ // To mimic behavior of the RI the InetAddress instance which was
+ // used to establish the connection is returned instead of one that
+ // was created by the native layer (this preserves exact hostnames).
+ if (address != null)
+ return address;
+
return remote.getAddress();
}
catch (IOException ioe)
@@ -471,6 +491,7 @@ public class PlainSocketImpl extends SocketImpl
{
if (channel == null)
return -1;
+
try
{
InetSocketAddress remote = channel.getVMChannel().getPeerAddress();
diff --git a/include/Makefile.am b/include/Makefile.am
index baa6fc0bd..b69b0ef73 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -125,7 +125,6 @@ $(XMLJ_H_FILES) \
$(GTKPEER_H_FILES) \
$(QTPEER_H_FILES) \
$(GCONF_PREFS_FILES) \
-$(top_srcdir)/include/gnu_java_net_VMPlainDatagramSocketImpl.h \
$(top_srcdir)/include/gnu_java_net_VMPlainSocketImpl.h \
$(top_srcdir)/include/gnu_java_net_local_LocalSocketImpl.h \
$(top_srcdir)/include/gnu_java_nio_EpollSelectorImpl.h \
@@ -180,8 +179,6 @@ $(top_srcdir)/include/gnu_javax_sound_midi_dssi_%.h: $(top_builddir)/$(CLASSDIR)
$(top_srcdir)/include/gnu_java_util_prefs_gconf_%.h: $(top_builddir)/$(CLASSDIR)/gnu/java/util/prefs/gconf/%.class
$(JAVAH) -o $@ gnu.java.util.prefs.gconf.$*
-$(top_srcdir)/include/gnu_java_net_VMPlainDatagramSocketImpl.h: $(top_srcdir)/vm/reference/gnu/java/net/VMPlainDatagramSocketImpl.java
- $(JAVAH) -o $@ gnu.java.net.VMPlainDatagramSocketImpl
$(top_srcdir)/include/gnu_java_net_VMPlainSocketImpl.h: $(top_srcdir)/vm/reference/gnu/java/net/VMPlainSocketImpl.java
$(JAVAH) -o $@ gnu.java.net.VMPlainSocketImpl
$(top_srcdir)/include/gnu_java_net_local_LocalSocketImpl.h: $(top_srcdir)/gnu/java/net/local/LocalSocketImpl.java
diff --git a/java/net/Socket.java b/java/net/Socket.java
index 439c29326..f4f25fe1c 100644
--- a/java/net/Socket.java
+++ b/java/net/Socket.java
@@ -298,8 +298,26 @@ public class Socket
laddr == null ? null : new InetSocketAddress(laddr, lport);
bind(bindaddr);
- // connect socket
- connect(new InetSocketAddress(raddr, rport));
+ // Connect socket in case of Exceptions we must close the socket
+ // because an exception in the constructor means that the caller will
+ // not have a reference to this instance.
+ // Note: You may have the idea that the exception treatment
+ // should be moved into connect() but there is a Mauve test which
+ // shows that a failed connect should not close the socket.
+ try
+ {
+ connect(new InetSocketAddress(raddr, rport));
+ }
+ catch (IOException ioe)
+ {
+ impl.close();
+ throw ioe;
+ }
+ catch (RuntimeException re)
+ {
+ impl.close();
+ throw re;
+ }
// FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
// i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
@@ -692,10 +710,10 @@ public class Socket
if (linger > 65535)
linger = 65535;
- getImpl().setOption(SocketOptions.SO_LINGER, new Integer(linger));
+ getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger));
}
else
- getImpl().setOption(SocketOptions.SO_LINGER, Boolean.valueOf(false));
+ getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1));
}
/**
@@ -1190,7 +1208,7 @@ public class Socket
{
if (impl == null)
return false;
-
+
return impl.getInetAddress() != null;
}
@@ -1223,6 +1241,7 @@ public class Socket
public boolean isClosed()
{
SocketChannel channel = getChannel();
+
return impl == null || (channel != null && ! channel.isOpen());
}
diff --git a/native/jni/java-net/Makefile.am b/native/jni/java-net/Makefile.am
index b743f2ffe..1278b946c 100644
--- a/native/jni/java-net/Makefile.am
+++ b/native/jni/java-net/Makefile.am
@@ -13,7 +13,6 @@ libjavanet_la_SOURCES = javanet.c \
java_net_VMInetAddress.c \
java_net_VMNetworkInterface.c \
java_net_VMURLConnection.c \
- gnu_java_net_VMPlainDatagramSocketImpl.c \
gnu_java_net_VMPlainSocketImpl.c \
$(local_sources)
diff --git a/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c b/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c
index ced3fe05c..53ef04d47 100644
--- a/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c
+++ b/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c
@@ -49,6 +49,7 @@ exception statement from your version. */
#include <ifaddrs.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
+#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -58,16 +59,14 @@ exception statement from your version. */
#include <jni.h>
#include <jcl.h>
-/* #include "javanet.h" */
+#include "cpnative.h"
+#include "cpnet.h"
+#include "cpio.h"
+#include "javanet.h"
#include "gnu_java_net_VMPlainSocketImpl.h"
-#define IO_EXCEPTION "java/io/IOException"
-#define SOCKET_EXCEPTION "java/net/SocketException"
-#define BIND_EXCEPTION "java/net/BindException"
-
-#define THROW_NO_NETWORK(env) JCL_ThrowException (env, "java/lang/InternalError", "this platform not configured for network support")
-
+#define THROW_NO_NETWORK(env) JCL_ThrowException (env, "java/lang/InternalError", "this platform not configured for network support")
/*
* Class: gnu_java_net_VMPlainSocketImpl
@@ -104,6 +103,8 @@ Java_gnu_java_net_VMPlainSocketImpl_bind (JNIEnv *env,
if (-1 == ret)
JCL_ThrowException (env, BIND_EXCEPTION, strerror (errno));
+
+ cpio_closeOnExec(ret);
}
@@ -160,7 +161,10 @@ Java_gnu_java_net_VMPlainSocketImpl_listen (JNIEnv *env,
}
-/* These constants are also defined in java/net/SocketOptions.java */
+/* These constants are also defined in java/net/SocketOptions.java.
+ * Except for CPNET_IP_TTL which is defined in
+ * vm/reference/gnu/java/net/VMPlainSocketImpl.java .
+ */
enum java_sockopt {
CPNET_SO_KEEPALIVE = 0x8,
CPNET_SO_LINGER = 0x80,
@@ -175,7 +179,8 @@ enum java_sockopt {
CPNET_IP_MULTICAST_IF = 0x10,
CPNET_IP_MULTICAST_IF2 = 0x1F,
CPNET_IP_MULTICAST_LOOP = 0x12,
- CPNET_IP_TOS = 0x03
+ CPNET_IP_TOS = 0x03,
+ CPNET_IP_TTL = 0x1E61
};
@@ -197,7 +202,7 @@ Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env,
struct timeval _timeo;
void *optval = (void *) &_value;
socklen_t optlen = sizeof (int);
-
+
switch (joption)
{
case CPNET_IP_MULTICAST_LOOP:
@@ -211,7 +216,7 @@ Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env,
case CPNET_SO_LINGER:
optname = SO_LINGER;
- if (_value == 0)
+ if (_value == -1)
_linger.l_onoff = 0;
else
_linger.l_onoff = 1;
@@ -258,6 +263,11 @@ Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env,
optname = IP_TOS;
break;
+ case CPNET_IP_TTL:
+ level = IPPROTO_IP;
+ optname = IP_TTL;
+ break;
+
case CPNET_SO_BINDADDR:
case CPNET_IP_MULTICAST_IF:
case CPNET_IP_MULTICAST_IF2:
@@ -341,6 +351,11 @@ Java_gnu_java_net_VMPlainSocketImpl_getOption (JNIEnv *env,
optname = IP_TOS;
break;
+ case CPNET_IP_TTL:
+ level = IPPROTO_IP;
+ optname = IP_TTL;
+ break;
+
case CPNET_SO_BINDADDR:
case CPNET_IP_MULTICAST_IF:
case CPNET_IP_MULTICAST_IF2:
@@ -351,14 +366,108 @@ Java_gnu_java_net_VMPlainSocketImpl_getOption (JNIEnv *env,
if (getsockopt (fd, level, optname, optval, &optlen) == -1)
JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ /* Returns the linger value if it is enabled or -1 in case
+ * it is disabled. This is how the Java API expects it.
+ */
if (joption == CPNET_SO_LINGER)
- return linger.l_linger;
+ return (linger.l_onoff) ? linger.l_linger : -1;
if (joption == CPNET_SO_TIMEOUT)
return (timeo.tv_sec * 1000) + (timeo.tv_usec / 1000);
return value;
}
+JNIEXPORT void JNICALL
+Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface (JNIEnv *env,
+ jclass c __attribute__((unused)),
+ jint fd,
+ jint optionId __attribute__((unused)),
+ jobject addr)
+{
+ int result;
+ cpnet_address *cpaddr = _javanet_get_ip_netaddr (env, addr);
+
+ if ((*env)->ExceptionOccurred (env))
+ return;
+
+ result = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
+ (struct sockaddr *) cpaddr->data, cpaddr->len);
+
+ cpnet_freeAddress (env, cpaddr);
+
+ if (result == -1)
+ JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface6 (JNIEnv *env,
+ jclass c __attribute__((unused)),
+ jint fd,
+ jint optionId __attribute__((unused)),
+ jstring ifname)
+{
+#ifdef HAVE_SETSOCKOPT
+#ifdef HAVE_INET6
+ int result;
+ const char *str_ifname = JCL_jstring_to_cstring (env, ifname);
+ u_int if_index;
+
+ if ((*env)->ExceptionOccurred (env))
+ {
+ JCL_free_cstring(env, ifname, str_ifname);
+ return;
+ }
+
+ if_index = if_nametoindex(str_ifname);
+ if (!if_index)
+ {
+ JCL_free_cstring(env, ifname, str_ifname);
+ JCL_ThrowException (env, SOCKET_EXCEPTION, "interface does not exist");
+ return;
+ }
+
+ result = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ (u_int *) &if_index, sizeof(if_index));
+
+ JCL_free_cstring(env, ifname, str_ifname);
+
+ if (result == -1)
+ JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno));
+#else
+ (void) fd;
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "IPv6 support not available");
+#endif /* HAVE_INET6 */
+#else
+ (void) fd;
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "socket options not supported");
+#endif /* HAVE_SETSOCKOPT */
+}
+
+JNIEXPORT jobject JNICALL
+Java_gnu_java_net_VMPlainSocketImpl_getMulticastInterface (JNIEnv *env,
+ jclass c __attribute__((unused)),
+ jint fd,
+ jint optionId __attribute__((unused)))
+{
+ jobject obj;
+ cpnet_address *cpaddr;
+ int result = cpnet_getMulticastIF (env, fd, &cpaddr);
+
+ if (result != CPNATIVE_OK)
+ {
+ JCL_ThrowException (env, SOCKET_EXCEPTION,
+ cpnative_getErrorString (result));
+ return (0);
+ }
+
+ obj = _javanet_create_inetaddress (env, cpaddr);
+ cpnet_freeAddress (env, cpaddr);
+
+ return obj;
+}
+
/*
* Class: gnu_java_net_VMPlainSocketImpl
@@ -540,7 +649,7 @@ Java_gnu_java_net_VMPlainSocketImpl_leave6 (JNIEnv *env,
(*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
- if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
&maddr, sizeof (struct ipv6_mreq)))
JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
#else
diff --git a/native/jni/java-nio/gnu_java_nio_VMChannel.c b/native/jni/java-nio/gnu_java_nio_VMChannel.c
index 501d64772..33a4f66de 100644
--- a/native/jni/java-nio/gnu_java_nio_VMChannel.c
+++ b/native/jni/java-nio/gnu_java_nio_VMChannel.c
@@ -59,6 +59,7 @@ exception statement from your version. */
#include <jni.h>
#include <jcl.h>
+#include "cpio.h"
#include "gnu_java_nio_VMChannel.h"
#include "javanio.h"
@@ -66,7 +67,9 @@ exception statement from your version. */
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
+#define CONNECT_EXCEPTION "java/net/ConnectException"
#define IO_EXCEPTION "java/io/IOException"
+#define SOCKET_EXCEPTION "java/net/SocketException"
#define INTERRUPTED_IO_EXCEPTION "java/io/InterruptedIOException"
#define NON_READABLE_CHANNEL_EXCEPTION "java/nio/channels/NonReadableChannelException"
#define NON_WRITABLE_CHANNEL_EXCEPTION "java/nio/channels/NonWritableChannelException"
@@ -103,6 +106,7 @@ void JCL_print_buffer(JNIEnv *, struct JCL_buffer *);
int JCL_init_buffer(JNIEnv *, struct JCL_buffer *, jobject);
void JCL_release_buffer(JNIEnv *, struct JCL_buffer *, jobject, jint);
void JCL_cleanup_buffers(JNIEnv *, struct JCL_buffer *, jint, jobjectArray, jint, jlong);
+int JCL_thread_interrupted(JNIEnv *, jclass);
static jfieldID address_fid;
static jmethodID get_position_mid;
@@ -112,6 +116,7 @@ static jmethodID set_limit_mid;
static jmethodID has_array_mid;
static jmethodID array_mid;
static jmethodID array_offset_mid;
+static jmethodID thread_interrupted_mid;
jmethodID
get_method_id(JNIEnv *env, jclass clazz, const char *name,
@@ -121,7 +126,7 @@ get_method_id(JNIEnv *env, jclass clazz, const char *name,
/* NIODBG("name: %s; sig: %s", name, sig); */
if (mid == NULL)
{
- JCL_ThrowException(env, "java/lang/InternalError", name);
+ JCL_ThrowException(env, "java/lang/InternalError", name);
return NULL;
}
@@ -249,6 +254,13 @@ JCL_cleanup_buffers(JNIEnv *env,
}
+int
+JCL_thread_interrupted(JNIEnv *env, jclass c)
+{
+ return (int) (*env)->CallBooleanMethod(env, c, thread_interrupted_mid);
+}
+
+
/*
* Class: gnu_java_nio_VMChannel
* Method: stdin_fd
@@ -293,7 +305,7 @@ Java_gnu_java_nio_VMChannel_stderr_1fd (JNIEnv *env __attribute__((unused)),
JNIEXPORT void JNICALL
Java_gnu_java_nio_VMChannel_initIDs (JNIEnv *env,
- jclass clazz __attribute__ ((__unused__)))
+ jclass clazz)
{
jclass bufferClass = JCL_FindClass(env, "java/nio/Buffer");
jclass byteBufferClass = JCL_FindClass(env, "java/nio/ByteBuffer");
@@ -318,6 +330,8 @@ Java_gnu_java_nio_VMChannel_initIDs (JNIEnv *env,
has_array_mid = get_method_id(env, byteBufferClass, "hasArray", "()Z");
array_mid = get_method_id(env, byteBufferClass, "array", "()[B");
array_offset_mid = get_method_id(env, byteBufferClass, "arrayOffset", "()I");
+
+ thread_interrupted_mid = get_method_id(env, clazz, "isThreadInterrupted", "()Z");
}
JNIEXPORT void JNICALL
@@ -975,7 +989,8 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un
if ((*env)->GetArrayLength (env, addr) != 4)
{
- JCL_ThrowException (env, "java/io/IOException", "expecting 4-byte address");
+ JCL_ThrowException (env, SOCKET_EXCEPTION,
+ "expecting 4-byte address");
return JNI_FALSE;
}
@@ -986,7 +1001,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un
origflags = fcntl (fd, F_GETFL, 0);
if (origflags == -1)
{
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
/* Set nonblocking mode, if not already set. */
@@ -995,7 +1010,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un
flags = origflags | O_NONBLOCK;
if (fcntl (fd, F_SETFL, flags) == -1)
{
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
}
@@ -1024,7 +1039,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un
if (fcntl (fd, F_SETFL, origflags) == -1)
{
/* oops */
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
}
@@ -1035,7 +1050,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un
ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo);
if (ret == -1)
{
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
if (ret == 0) /* connect timed out */
@@ -1048,13 +1063,13 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un
}
else if (ECONNREFUSED == errno)
{
- JCL_ThrowException (env, "java/net/ConnectException",
+ JCL_ThrowException (env, CONNECT_EXCEPTION,
strerror (errno));
return JNI_FALSE;
}
else
{
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
}
@@ -1065,13 +1080,13 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un
return JNI_FALSE;
else if (ECONNREFUSED == errno)
{
- JCL_ThrowException (env, "java/net/ConnectException",
+ JCL_ThrowException (env, CONNECT_EXCEPTION,
strerror (errno));
return JNI_FALSE;
}
else
{
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
}
@@ -1082,7 +1097,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un
(void) addr;
(void) port;
(void) timeout;
- JCL_ThrowException (env, IO_EXCEPTION, "connect not supported");
+ JCL_ThrowException (env, SOCKET_EXCEPTION, "connect not supported");
return JNI_FALSE;
#endif /* HAVE_CONNECT */
}
@@ -1111,7 +1126,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u
origflags = fcntl (fd, F_GETFL, 0);
if (origflags == -1)
{
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
/* Set nonblocking mode, if not already set. */
@@ -1120,7 +1135,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u
flags = origflags | O_NONBLOCK;
if (fcntl (fd, F_SETFL, flags) == -1)
{
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
}
@@ -1148,7 +1163,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u
if (fcntl (fd, F_SETFL, origflags) == -1)
{
/* oops */
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
}
@@ -1159,7 +1174,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u
ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo);
if (ret == -1)
{
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
if (ret == 0) /* connect timed out */
@@ -1172,13 +1187,13 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u
}
else if (ECONNREFUSED == errno)
{
- JCL_ThrowException (env, "java/net/ConnectException",
+ JCL_ThrowException (env, CONNECT_EXCEPTION,
strerror (errno));
return JNI_FALSE;
}
else
{
- JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
}
@@ -1189,13 +1204,13 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u
return JNI_FALSE;
else if (ECONNREFUSED == errno)
{
- JCL_ThrowException (env, "java/net/ConnectException",
+ JCL_ThrowException (env, CONNECT_EXCEPTION,
strerror (errno));
return JNI_FALSE;
}
else
{
- JCL_ThrowException (env, "java/io/IOException", strerror (errno));
+ JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
return JNI_FALSE;
}
}
@@ -1206,7 +1221,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u
(void) addr;
(void) port;
(void) timeout;
- JCL_ThrowException (env, IO_EXCEPTION, "IPv6 connect not supported");
+ JCL_ThrowException (env, SOCKET_EXCEPTION, "IPv6 connect not supported");
return JNI_FALSE;
#endif /* HAVE_CONNECT && HAVE_INET6 */
}
@@ -1340,11 +1355,12 @@ Java_gnu_java_nio_VMChannel_getpeername (JNIEnv *env, jclass clazz __attribute__
*/
JNIEXPORT jint JNICALL
Java_gnu_java_nio_VMChannel_accept (JNIEnv *env,
- jclass clazz __attribute__((unused)),
+ jclass clazz,
jint fd)
{
#ifdef HAVE_ACCEPT
int ret;
+ int tmp_errno = 0;
#ifdef HAVE_INET6
struct sockaddr_in6 addr;
@@ -1357,14 +1373,38 @@ Java_gnu_java_nio_VMChannel_accept (JNIEnv *env,
do
{
ret = cpnio_accept (fd, (struct sockaddr *) &addr, &alen);
+ tmp_errno = errno;
+
+ if (ret == -1)
+ switch (tmp_errno)
+ {
+ case EINTR:
+ /* Check if interrupted by Thread.interrupt(). If not then some
+ * other unrelated signal interrupted the system function and
+ * we should start over again.
+ */
+ if (JCL_thread_interrupted(env, clazz))
+ {
+ JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno));
+ return -1;
+ }
+ break;
+#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ case EAGAIN:
+ /* Socket in non-blocking mode and no pending connection. */
+ return -1;
+ default:
+ JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno));
+ return -1;
+ }
+ else
+ break;
}
- while (ret == -1 && EINTR == errno);
+ while (1);
- if (ret == -1)
- {
- if (EWOULDBLOCK != ret && EAGAIN != ret)
- JCL_ThrowException (env, "java/net/SocketException", strerror (errno));
- }
+ cpio_closeOnExec(ret);
return ret;
#else
diff --git a/native/jni/native-lib/cpio.c b/native/jni/native-lib/cpio.c
index 4d23b7a1f..2777a31b2 100644
--- a/native/jni/native-lib/cpio.c
+++ b/native/jni/native-lib/cpio.c
@@ -473,3 +473,13 @@ int cpio_readDir (void *handle, char *filename)
strncpy (filename, dBuf->d_name, FILENAME_MAX);
return 0;
}
+
+
+int
+cpio_closeOnExec(int fd)
+{
+ if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1)
+ return errno;
+
+ return 0;
+}
diff --git a/native/jni/native-lib/cpio.h b/native/jni/native-lib/cpio.h
index 97483d294..b388b5b50 100644
--- a/native/jni/native-lib/cpio.h
+++ b/native/jni/native-lib/cpio.h
@@ -64,6 +64,7 @@ JNIEXPORT int cpio_read (int fd, void *data, jint len, jint *bytes_read);
JNIEXPORT int cpio_write (int fd, const void *data, jint len, jint *bytes_written);
JNIEXPORT int cpio_fsync (int fd);
JNIEXPORT int cpio_truncate (int fd, jlong size);
+JNIEXPORT int cpio_closeOnExec(int fd);
#define CPFILE_FILE 0
#define CPFILE_DIRECTORY 1
diff --git a/vm/reference/gnu/java/net/VMPlainSocketImpl.java b/vm/reference/gnu/java/net/VMPlainSocketImpl.java
index 126294c7f..916f95930 100644
--- a/vm/reference/gnu/java/net/VMPlainSocketImpl.java
+++ b/vm/reference/gnu/java/net/VMPlainSocketImpl.java
@@ -43,15 +43,11 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
-import java.net.SocketAddress;
import java.net.SocketException;
-import java.net.SocketImpl;
import java.net.SocketOptions;
-import java.net.UnknownHostException;
import gnu.classpath.Configuration;
import gnu.java.nio.VMChannel;
-import gnu.java.nio.VMChannel.State;
/**
* The VM interface for {@link gnu.java.net.PlainSocketImpl}.
@@ -61,6 +57,10 @@ import gnu.java.nio.VMChannel.State;
*/
public final class VMPlainSocketImpl
{
+ /** Option id for time to live
+ */
+ private static final int CP_IP_TTL = 0x1E61;
+
private final State nfd;
/**
@@ -91,6 +91,41 @@ public final class VMPlainSocketImpl
return nfd;
}
+ /** This method exists to hide the CP_IP_TTL value from
+ * higher levels.
+ *
+ * Always think of JNode ... :)
+ */
+ public void setTimeToLive(int ttl)
+ throws SocketException
+ {
+ try
+ {
+ setOption(nfd.getNativeFD(), CP_IP_TTL, ttl);
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
+ }
+
+ public int getTimeToLive()
+ throws SocketException
+ {
+ try
+ {
+ return getOption(nfd.getNativeFD(), CP_IP_TTL);
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
+ }
+
public void setOption(int optionId, Object optionValue)
throws SocketException
{
@@ -98,7 +133,14 @@ public final class VMPlainSocketImpl
if (optionValue instanceof Integer)
value = ((Integer) optionValue).intValue();
else if (optionValue instanceof Boolean)
- value = ((Boolean) optionValue).booleanValue() ? 1 : 0;
+ // Switching off the linger behavior is done by setting
+ // the value to -1. This is how the Java API interprets
+ // it.
+ value = ((Boolean) optionValue).booleanValue()
+ ? 1
+ : (optionId == SocketOptions.SO_LINGER)
+ ? -1
+ : 0;
else
throw new IllegalArgumentException("option value type "
+ optionValue.getClass().getName());
@@ -118,6 +160,41 @@ public final class VMPlainSocketImpl
private static native void setOption(int fd, int id, int value)
throws SocketException;
+ public void setMulticastInterface(int optionId, InetAddress addr)
+ throws SocketException
+ {
+ try
+ {
+ if (addr instanceof Inet4Address)
+ setMulticastInterface(nfd.getNativeFD(), optionId, (Inet4Address) addr);
+ else if (addr instanceof Inet6Address)
+ {
+ NetworkInterface iface = NetworkInterface.getByInetAddress(addr);
+ setMulticastInterface6(nfd.getNativeFD(), optionId, iface.getName());
+ }
+ else
+ throw new SocketException("Unknown address format: " + addr);
+ }
+ catch (SocketException se)
+ {
+ throw se;
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
+ }
+
+ private static native void setMulticastInterface(int fd,
+ int optionId,
+ Inet4Address addr);
+
+ private static native void setMulticastInterface6(int fd,
+ int optionId,
+ String ifName);
+
/**
* Get a socket option. This implementation is only required to support
* socket options that are boolean values, which include:
@@ -126,6 +203,7 @@ public final class VMPlainSocketImpl
* SocketOptions.SO_BROADCAST
* SocketOptions.SO_KEEPALIVE
* SocketOptions.SO_OOBINLINE
+ * SocketOptions.SO_REUSEADDR
* SocketOptions.TCP_NODELAY
*
* and socket options that are integer values, which include:
@@ -161,6 +239,7 @@ public final class VMPlainSocketImpl
case SocketOptions.SO_BROADCAST:
case SocketOptions.SO_KEEPALIVE:
case SocketOptions.SO_OOBINLINE:
+ case SocketOptions.SO_REUSEADDR:
case SocketOptions.TCP_NODELAY:
return Boolean.valueOf(value != 0);
@@ -178,6 +257,33 @@ public final class VMPlainSocketImpl
}
private static native int getOption(int fd, int id) throws SocketException;
+
+ /**
+ * Returns an Inet4Address or Inet6Address instance belonging to the
+ * interface which is set as the multicast interface.
+ *
+ * The optionId is provided to make it possible that the native
+ * implementation may do something different depending on whether
+ * the value is SocketOptions.IP_MULTICAST_IF or
+ * SocketOptions.IP_MULTICAST_IF2.
+ */
+ public InetAddress getMulticastInterface(int optionId)
+ throws SocketException
+ {
+ try
+ {
+ return getMulticastInterface(nfd.getNativeFD(), optionId);
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
+ }
+
+ private static native InetAddress getMulticastInterface(int fd,
+ int optionId);
/**
* Binds this socket to the given local address and port.
@@ -402,4 +508,5 @@ public final class VMPlainSocketImpl
}
}
}
-} \ No newline at end of file
+}
+
diff --git a/vm/reference/gnu/java/nio/VMChannel.java b/vm/reference/gnu/java/nio/VMChannel.java
index 688a94ac4..39ee4edb6 100644
--- a/vm/reference/gnu/java/nio/VMChannel.java
+++ b/vm/reference/gnu/java/nio/VMChannel.java
@@ -39,7 +39,6 @@ exception statement from your version. */
package gnu.java.nio;
import gnu.classpath.Configuration;
-import gnu.classpath.jdwp.exception.NotImplementedException;
import java.io.IOException;
import java.net.Inet4Address;
@@ -379,23 +378,37 @@ public final class VMChannel
* @throws IOException If an error occurs while connecting.
*/
public boolean connect(InetSocketAddress saddr, int timeout)
- throws IOException
+ throws SocketException
{
+ int fd;
+
InetAddress addr = saddr.getAddress();
+
+ // Translates an IOException into a SocketException to conform
+ // to the throws clause.
+ try
+ {
+ fd = nfd.getNativeFD();
+ }
+ catch (IOException ioe)
+ {
+ throw new SocketException(ioe.getMessage());
+ }
+
if (addr instanceof Inet4Address)
- return connect(nfd.getNativeFD(), addr.getAddress(), saddr.getPort(),
+ return connect(fd, addr.getAddress(), saddr.getPort(),
timeout);
if (addr instanceof Inet6Address)
- return connect6(nfd.getNativeFD(), addr.getAddress(), saddr.getPort(),
+ return connect6(fd, addr.getAddress(), saddr.getPort(),
timeout);
- throw new IOException("unsupported internet address");
+ throw new SocketException("unsupported internet address");
}
private static native boolean connect(int fd, byte[] addr, int port, int timeout)
- throws IOException;
+ throws SocketException;
private static native boolean connect6(int fd, byte[] addr, int port, int timeout)
- throws IOException;
+ throws SocketException;
/**
* Disconnect this channel, if it is a datagram socket. Disconnecting
@@ -614,6 +627,17 @@ public final class VMChannel
}
static native void close(int native_fd) throws IOException;
+
+ /**
+ * <p>Provides a simple mean for the JNI code to find out whether the
+ * current thread was interrupted by a call to Thread.interrupt().</p>
+ *
+ * @return
+ */
+ final boolean isThreadInterrupted()
+ {
+ return Thread.currentThread().isInterrupted();
+ }
// Inner classes.