diff options
author | Robert Schuster <theBohemian@gmx.net> | 2006-10-25 00:33:26 +0000 |
---|---|---|
committer | Robert Schuster <theBohemian@gmx.net> | 2006-10-25 00:33:26 +0000 |
commit | 707979fc1851cc48342c3fbf08245c69430ca2c9 (patch) | |
tree | 368591120d13fcf2c0dd884d4aa70b2edc9f0fbc | |
parent | 349c427b949b8ddd65ee40301ce3365bd13f8fda (diff) | |
download | classpath-707979fc1851cc48342c3fbf08245c69430ca2c9.tar.gz |
Lots of changes.
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.
-rw-r--r-- | ChangeLog | 71 | ||||
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | gnu/java/net/PlainDatagramSocketImpl.java | 57 | ||||
-rw-r--r-- | gnu/java/net/PlainSocketImpl.java | 55 | ||||
-rw-r--r-- | include/Makefile.am | 3 | ||||
-rw-r--r-- | java/net/Socket.java | 29 | ||||
-rw-r--r-- | native/jni/java-net/Makefile.am | 1 | ||||
-rw-r--r-- | native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c | 135 | ||||
-rw-r--r-- | native/jni/java-nio/gnu_java_nio_VMChannel.c | 96 | ||||
-rw-r--r-- | native/jni/native-lib/cpio.c | 10 | ||||
-rw-r--r-- | native/jni/native-lib/cpio.h | 1 | ||||
-rw-r--r-- | vm/reference/gnu/java/net/VMPlainSocketImpl.java | 119 | ||||
-rw-r--r-- | vm/reference/gnu/java/nio/VMChannel.java | 38 |
13 files changed, 520 insertions, 101 deletions
@@ -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. @@ -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. |