summaryrefslogtreecommitdiff
path: root/vm
diff options
context:
space:
mode:
authorCasey Marshall <csm@gnu.org>2006-09-17 07:31:39 +0000
committerCasey Marshall <csm@gnu.org>2006-09-17 07:31:39 +0000
commit133e014be0604b45f8ccede687acf1ea979d4955 (patch)
tree03bfec201e509081586497b0e4db7944e633cab7 /vm
parenta344c95abdd44f1c697d0520bf97ac3c8403a3b6 (diff)
downloadclasspath-133e014be0604b45f8ccede687acf1ea979d4955.tar.gz
2006-09-16 Casey Marshall <csm@gnu.org>
* NEWS: updated. * configure.ac (AC_CHECK_HEADERS): check for `sys/event.h'. (AC_CHECK_FUNCS): add checks for readv, writev, getifaddrs, kqueue, and kevent. (HAVE_INET6): define if IPv6 is supported. * gnu/java/net/PlainDatagramSocketImpl.java (channel): new field. (native_fd): removed. (impl): new field. (<init>): throw IOException; initialize fields. (finalize): removed. (getNativeFD): removed. (bind): use `PlainSocketImpl.bind.' (create): use `PlainSocketImpl.initSocket.' (disconnect): use `PlainSocketImpl.disconnect.' (getLocalPort): new method. (send): use `VMChannel.send.' (receive): use `VMChannel.receive.' (setOption): use `PlainSocketImpl.setOption.' (getOption): use `PlainSocketImpl.getOption.' (close): use `VMChannel.State.close.' (join): use `PlainSocketImpl.join.' (leave): use `PlainSocketImpl.leave.' (joinGroup, leaveGroup): implemented. * gnu/java/net/PlainSocketImpl.java: make non-final. (native_fd): removed. (impl): new field. (channel): new field. (<init>): initialize `impl.' (finalize, getNativeFD): removed. (setOption): use `PlainSocketImpl.setOption.' (getOption): use `PlainSocketImpl.getOption.' (shutdownInput): use `PlainSocketImpl.shutdownInput.' (shutdownOutput): use `PlainSocketImpl.shutdownOutput.' (create): create `channel,' initialize `impl's native state. (connect): use `connect(SocketAddress, int).' (connect): use `SocketChannelImpl.connect;' initialize `address' and `port.' (bind): use `VMPlainSocketImpl.bind.' (listen): use `VMPlainSocketImpl.listen.' (accept): use `SocketChannelImpl.accept.' (available): use `VMChannel.available.' (close): use `PlainSocketImpl.close.' (sendUrgentData): use `PlainSocketImpl.sendUrgentData.' (getVMChannel, getInetAddress, getLocalPort, getLocalAddress, getPort): new methods. (SocketInputStream.read): use `VMChannel.read.' (SocketInputStream.read): use `SocketChannel.read.' (SocketOutputStream.write): use `VMChannel.write.' (SocketOutputStream.write): use `SocketChannel.write.' * gnu/java/nio/DatagramChannelImpl.java: implement VMChannel. (channel): new field. (<init>): initialize `channel.' (implCloseSelectableChannel): use `VMChannel.close.' (implConfigureBlocking): use `VMChannel.setBlocking.' (connect): use `VMChannel.connect.' (disconnect): use `VMChannel.disconnect.' (isConnected): use `VMChannel.getPeerAddress.' (write): use `VMChannel.write.' (write): use `VMChannel.writeGathering.' (read): use `VMChannel.read.' (read): use `VMChannel.readScattering.' (receive): use `VMChannel.receive.' (send): use `VMChannel.send.' (getVMChannel): new method. * gnu/java/nio/DatagramChannelSelectionKey.java (getNativeFD): access native FD through VMChannel.State. * gnu/java/nio/FileChannelImpl.java: moved from gnu/java/nio/channels/FileChannelImpl.java. * gnu/java/nio/FileLockImpl.java: fix imports. * gnu/java/nio/KqueueSelectionKeyImpl.java: new file. * gnu/java/nio/KqueueSelectorImpl.java: new file. * gnu/java/nio/NIOSocket.java (impl): removed. (channel): new field. (<init>): init superclass with a `NIOSocketImpl;' init `channel.' (getPlainSocketImpl, setChannel): removed. (isConnected): new method. * gnu/java/nio/NIOSocketImpl.java: new file. * gnu/java/nio/PipeImpl.java (SourceChannelImpl): implement `VMChannelOwner.' (SourceChannelImpl.native_fd): removed. (SourceChannelImpl.<init>): init with a `VMChannel.' (SourceChannelImpl.getNativeFD): removed. (SourceChannelImpl.getVMChannel): new method. (SourceChannelImpl.implCloseSelectableChannel): implement. (SinkChannelImpl): implement `VMChannelOwner.' (SinkChannelImpl.native_fd): removed. (SinkChannelImpl.<init>): init with a `VMChannel.' (SinkChannelImpl.implCloseSelectableChannel): implement. (SinkChannelImpl.getNativeFD): removed. (SinkChannelImpl.getVMChannel): new method. * gnu/java/nio/SelectionKeyImpl.java (getNativeFD): mark deprecated. * gnu/java/nio/SelectorProviderImpl.java (SELECTOR_IMPL_KQUEUE, SELECTOR_IMPL_EPOLL, SELECTOR_IMPL): new constants. (openSelector): return kqueue selector if available. * gnu/java/nio/ServerSocketChannelImpl.java: implement `VMChannelOwner.' (channel): new field. (<init>): init `channel.' (finalizer): check if the `VMChannel.State' is valid. (implCloseSelectableChannel): use `VMChannel.close.' (implConfigureBlocking): use `VMChannel.setBlocking.' (accept): use `VMChannel.accept.' (getVMChannel): new method. * gnu/java/nio/ServerSocketChannelSelectionKey.java (getNativeFD): access native FD through `VMChannel.State.' * gnu/java/nio/SocketChannelImpl.java: implement `VMChannelOwner.' (impl): removed. (channel, connected, connectAddress): new field. (<init>): new constructors. (getPlainSocketImpl): removed. (implCloseSelectableChannel): use `VMChannel.close.' (implConfigureBlocking): use `VMChannel.setBlocking.' (connect): use `connect(SocketAddress,int).' (connect): use `VMChannel.connect.' (finishConnect): don't use a selector. (isConnected): use `VMChannel.getPeerAddress.' (read): use `VMChannel.read.' (read): use `VMChannel.readScattering.' (write): use `VMChannel.write.' (write): use `VMChannel.writeGathering.' (getVMChannel): new method. * gnu/java/nio/SocketChannelSelectionKey.java (getNativeFD): get native FD from `VMChannel.State.' * gnu/java/nio/SocketChannelSelectionKeyImpl.java (getNativeFD): get native FD from `VMChannel.State.' * gnu/java/nio/VMChannelOwner.java: new file. * gnu/java/nio/channels/FileChannelImpl.java: removed. * include/Makefile.am: generate `gnu_java_nio_FileChannelImpl.h' and `gnu_java_nio_KqueueSelectorImpl.h;' don't generate `gnu_java_nio_channels_FileChannelImpl.h.' * include/gnu_java_net_VMPlainSocketImpl.h: regenerated. * include/gnu_java_nio_FileChannelImpl.h: new file. * include/gnu_java_nio_KqueueSelectorImpl.h: new file. * include/gnu_java_nio_VMChannel.h: regenerated. * include/gnu_java_nio_VMPipe.h: regenerated. * include/java_net_VMNetworkInterface.h: regenerated. * java/io/FileDescriptor.java: fix imports. * java/io/FileInputStream.java (<init>): handle exceptions. (read): wrap the destination arary. * java/io/FileOutputStream.java (<init>): handle exceptions. (write): wrap the source array. * java/io/RandomAccessFile.java (<init>): handle exceptions. * java/net/DatagramSocket.java (<init>): handle exceptions. (receive): handle length/port setting. (connect): bind to any address/port if the argument is null. * java/net/NetworkInterface.java (name, inetAddress): removed. (netif): new field. (<init>): make private. (getName): return `netif.name.' (getInetAddresses): access `netif.addresses.' (getDisplayName): return `netif.name.' (getByName, getByAddress): handle changes to `VMNetworkInterface.' (condense): removed. (getNetworkInterfaces): handle changes to `VMNetworkInterface.' (equals): compare `netif' fields. (hashCode): get hash codes from `netif.' (toString): use a StringBuffer. * java/net/ServerSocket.java (close): don't set `impl' to null. (isClosed): use `VMChannel.State.isClosed.' * java/net/Socket.java (getLocalAddress): don't use `getOption' if the `SocketImpl' is a `PlainSocketImpl.' (close): just close the `impl.' (toString): use `super.toString' in the value we return. (isConnected): just access `impl,' not `getImpl.' (isBound): use `PlainSocketImpl' methods if we can. (isClosed): look at `VMChannel.State.' * native/jni/classpath/jcl.c (JNI_OnLoad): new function. (JCL_NewRawDataObject): don't initialize cached fields here; throw an exception if they were not. (JCL_GetRawData): throw an exception if cached fields weren't created. * native/jni/java-lang/java_lang_VMProcess.c: handle FileChannelImpl move. * native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c (IO_EXCEPTION, SOCKET_EXCEPTION, BIND_EXCEPTION, THROW_NO_NETWORK): new macros. (Java_gnu_java_net_VMPlainSocketImpl_bind): reipmlemented. (Java_gnu_java_net_VMPlainSocketImpl_bind6): new function. (Java_gnu_java_net_VMPlainSocketImpl_listen): reimplemented. (java_sockopt): new enum. (Java_gnu_java_net_VMPlainSocketImpl_setOption): reimplemented. (Java_gnu_java_net_VMPlainSocketImpl_getOption): reimplemented. (Java_gnu_java_net_VMPlainSocketImpl_shutdownInput): reimplemented. (Java_gnu_java_net_VMPlainSocketImpl_shutdownOutput): reimplemented. (Java_gnu_java_net_VMPlainSocketImpl_sendUrgentData): new function. (Java_gnu_java_net_VMPlainSocketImpl_join): new function. (Java_gnu_java_net_VMPlainSocketImpl_join6): new function. (Java_gnu_java_net_VMPlainSocketImpl_read): removed. (Java_gnu_java_net_VMPlainSocketImpl_leave): new function. (Java_gnu_java_net_VMPlainSocketImpl_leave6): new function. (Java_gnu_java_net_VMPlainSocketImpl_joinGroup): new function. (Java_gnu_java_net_VMPlainSocketImpl_write): removed. (Java_gnu_java_net_VMPlainSocketImpl_joinGroup6): new function. (Java_gnu_java_net_VMPlainSocketImpl_leaveGroup): new function. (Java_gnu_java_net_VMPlainSocketImpl_leaveGroup6): new function. (getif_address): new function. (getif_index): new function. * native/jni/java-net/java_net_VMNetworkInterface.c (java_net_VMNetworkInterface_init, java_net_VMNetworkInterface_addAddress): new file-scope globals. (Java_java_net_VMNetworkInterface_initIds): new function. (struct netif_entry): new struct. (free_netif_list): new function. (Java_java_net_VMNetworkInterface_getInterfaces): removed. (Java_java_net_VMNetworkInterface_getVMInterfaces): new function. * native/jni/java-nio/Makefile.am (libjavanio_la_SOURCES): remove gnu_java_nio_channels_FileChannelImpl.c, add gnu_java_nio_KqueueSelectorImpl.c. * native/jni/java-nio/gnu_java_nio_KqueueSelectorImpl.c: new file. * native/jni/java-nio/gnu_java_nio_VMChannel.c (INTERRUPTED_IO_EXCEPTION, SOCKET_TIMEOUT_EXCEPTION, ALIGN_UP, ALIGN_DOWN): new macros. (JCL_init_buffer): get the address through GetDirectBufferAddress if possible. (Java_gnu_java_nio_VMChannel_stdin_1fd, Java_gnu_java_nio_VMChannel_stdout_1fd, Java_gnu_java_nio_VMChannel_stderr_1fd): new functions. (Java_gnu_java_nio_VMChannel_setBlocking): fix setting blocking value. (Java_gnu_java_nio_VMChannel_read): renamed... (Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2): to this; handle interrupted IO; add HAVE_READ check. (Java_gnu_java_nio_VMChannel_write): renamed... (Java_gnu_java_nio_VMChannel_write__ILjava_nio_ByteBuffer_2): to this; handle zero-length write; add HAVE_WRITE check. (Java_gnu_java_nio_VMChannel_receive): new function. (Java_gnu_java_nio_VMChannel_send): new function. (Java_gnu_java_nio_VMChannel_send6): new function. (Java_gnu_java_nio_VMChannel_read__I): new function. (Java_gnu_java_nio_VMChannel_write__II): new function. (Java_gnu_java_nio_VMChannel_socket): new function. (Java_gnu_java_nio_VMChannel_connect): new function. (Java_gnu_java_nio_VMChannel_connect6): new function. (Java_gnu_java_nio_VMChannel_getsockname): new function. (Java_gnu_java_nio_VMChannel_getpeername): new function. (Java_gnu_java_nio_VMChannel_accept): new function. (Java_gnu_java_nio_VMChannel_disconnect): new function. (Java_gnu_java_nio_VMChannel_close): new function. (Java_gnu_java_nio_VMChannel_available): new function. (FileChannel_mode): new enum. (Java_gnu_java_nio_VMChannel_open): new function. (Java_gnu_java_nio_VMChannel_position): new function. (Java_gnu_java_nio_VMChannel_seek): new function. (Java_gnu_java_nio_VMChannel_truncate): new funciton. (Java_gnu_java_nio_VMChannel_lock): new function. (Java_gnu_java_nio_VMChannel_unlock): new function. (Java_gnu_java_nio_VMChannel_size): new function. (Java_gnu_java_nio_VMChannel_map): new function. (Java_gnu_java_nio_VMChannel_flush): new function. * native/jni/java-nio/gnu_java_nio_VMPipe.c (Java_gnu_java_nio_VMPipe_init): removed. (Java_gnu_java_nio_VMPipe_pipe0): new function. * native/jni/java-nio/javanio.c: new file. * native/jni/java-nio/javanio.h: new file. * native/jni/native-lib/cpnet.c (cpnet_getHostByName): fix for systems without `gethostbyname_r.' * vm/reference/gnu/java/net/VMPlainSocketImpl.java (nfd): new field. (<init>, <init>): new constructors. (setOption, getOption): make instance methods; defer to native implementation. (connect): removed. (bind): make an instance method; defer to native methods. (accept): removed. (available): removed. (listen): make an instance method; defer to native method. (read): removed. (join, leave): new methods. (write): removed. (joinGroup, leaveGroup): new methods. (shutdownInput, shutdownOutput): make instance methods. (sendUrgentData): removed. (State): new class. * vm/reference/gnu/java/nio/VMChannel.java: make final. (fd): removed. (nfd): new field. (<init>): new, public constructors. (getVMChannel): methods removed. (getState, getStdin, getStdout, getStderr, stdin_fd, stdout_fd, stderr_fd): new methods. (setBlocking): make an instance method. (available): new method. (read): get native fd from `nfd.' (read): new single-byte read method. (readScattering): get native fd from `nfd.' (receive): new method. (write, writeGathering): get native fd from `nfd.' (send): new method. (write): new single-byte write method. (initSocket): new method. (connect): new method. (disconnect): new method. (getLocalAddress): new method. (getPeerAddress): new method. (accept): new method. (openFile): new method. (position): new method. (seek): new method. (truncate): new method. (lock): new method. (unlock): new method. (size): new method. (map): new method. (flush): new method. (close): new method. (State): new class. (Kind): new class. * vm/reference/gnu/java/nio/VMPipe.java (init): removed. (pipe, pipe0): new method. * vm/reference/java/net/VMNetworkInterface.java (name, addresses): new fields. (<clinit>): call `initIds.' (initIds): new method. (getInterfaces): removed. (getVMInterfaces): new method. (addAddress): new method. * vm/reference/java/nio/channels/VMChannels.java: fix imports.
Diffstat (limited to 'vm')
-rw-r--r--vm/reference/gnu/java/net/VMPlainSocketImpl.java505
-rw-r--r--vm/reference/gnu/java/nio/VMChannel.java611
-rw-r--r--vm/reference/gnu/java/nio/VMPipe.java23
-rw-r--r--vm/reference/java/net/VMNetworkInterface.java57
-rw-r--r--vm/reference/java/nio/channels/VMChannels.java2
5 files changed, 928 insertions, 270 deletions
diff --git a/vm/reference/gnu/java/net/VMPlainSocketImpl.java b/vm/reference/gnu/java/net/VMPlainSocketImpl.java
index 76be558dc..126294c7f 100644
--- a/vm/reference/gnu/java/net/VMPlainSocketImpl.java
+++ b/vm/reference/gnu/java/net/VMPlainSocketImpl.java
@@ -38,8 +38,11 @@ exception statement from your version. */
package gnu.java.net;
import java.io.IOException;
+import java.net.Inet4Address;
+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;
@@ -47,6 +50,8 @@ 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}.
@@ -56,6 +61,8 @@ import gnu.classpath.Configuration;
*/
public final class VMPlainSocketImpl
{
+ private final State nfd;
+
/**
* Static initializer to load native library.
*/
@@ -66,249 +73,333 @@ public final class VMPlainSocketImpl
System.loadLibrary("javanet");
}
}
+
+ public VMPlainSocketImpl()
+ {
+ // XXX consider adding security check here.
+ nfd = new State();
+ }
+
+ public VMPlainSocketImpl(VMChannel channel) throws IOException
+ {
+ this();
+ nfd.setChannelFD(channel.getState());
+ }
+
+ public State getState()
+ {
+ return nfd;
+ }
- /**
- * Sets the specified option on a socket to the passed in object.
- * The optionId parameter is one of the defined constants in
- * the SocketImpl interface.
- *
- * @param socket the socket object
- * @param optionId the identifier of the option
- * @param value the value to set the option to
- *
- * @throws SocketException if an error occurs
- */
- static native void setOption(PlainSocketImpl socket, int optionId, Object value)
- throws SocketException;
-
- /**
- * Returns the current setting of the specified option. The optionId
- * is one of the defined constants in this interface.
- *
- * @param socket the socket object
- * @param optionId the option identifier
- *
- * @return the current value of the option
- *
- * @throws SocketException ff an error occurs
- */
- static native Object getOption(PlainSocketImpl socket, int optionId)
+ public void setOption(int optionId, Object optionValue)
+ throws SocketException
+ {
+ int value;
+ if (optionValue instanceof Integer)
+ value = ((Integer) optionValue).intValue();
+ else if (optionValue instanceof Boolean)
+ value = ((Boolean) optionValue).booleanValue() ? 1 : 0;
+ else
+ throw new IllegalArgumentException("option value type "
+ + optionValue.getClass().getName());
+
+ try
+ {
+ setOption(nfd.getNativeFD(), optionId, value);
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
+ }
+
+ private static native void setOption(int fd, int id, int value)
throws SocketException;
/**
- * Creates a new socket that is not bound to any local address/port and
- * is not connected to any remote address/port.
- *
- * @param socket the socket object
- *
- * @throws IOException if something goes wrong while creating the socket
+ * Get a socket option. This implementation is only required to support
+ * socket options that are boolean values, which include:
+ *
+ * SocketOptions.IP_MULTICAST_LOOP
+ * SocketOptions.SO_BROADCAST
+ * SocketOptions.SO_KEEPALIVE
+ * SocketOptions.SO_OOBINLINE
+ * SocketOptions.TCP_NODELAY
+ *
+ * and socket options that are integer values, which include:
+ *
+ * SocketOptions.IP_TOS
+ * SocketOptions.SO_LINGER
+ * SocketOptions.SO_RCVBUF
+ * SocketOptions.SO_SNDBUF
+ * SocketOptions.SO_TIMEOUT
+ *
+ * @param optionId The option ID to fetch.
+ * @return A {@link Boolean} or {@link Integer} containing the socket
+ * option.
+ * @throws SocketException
*/
- static native void create(PlainSocketImpl socket) throws IOException;
-
+ public Object getOption(int optionId) throws SocketException
+ {
+ int value;
+ try
+ {
+ value = getOption(nfd.getNativeFD(), optionId);
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
+
+ switch (optionId)
+ {
+ case SocketOptions.IP_MULTICAST_LOOP:
+ case SocketOptions.SO_BROADCAST:
+ case SocketOptions.SO_KEEPALIVE:
+ case SocketOptions.SO_OOBINLINE:
+ case SocketOptions.TCP_NODELAY:
+ return Boolean.valueOf(value != 0);
+
+ case SocketOptions.IP_TOS:
+ case SocketOptions.SO_LINGER:
+ case SocketOptions.SO_RCVBUF:
+ case SocketOptions.SO_SNDBUF:
+ case SocketOptions.SO_TIMEOUT:
+ return new Integer(value);
+
+ default:
+ throw new SocketException("getting option " + optionId +
+ " not supported here");
+ }
+ }
+
+ private static native int getOption(int fd, int id) throws SocketException;
+
/**
- * Connects to the remote address and port specified as arguments.
+ * Binds this socket to the given local address and port.
*
- * @param socket the socket object
- * @param addr the remote address to connect to
- * @param port the remote port to connect to
- *
- * @throws IOException if an error occurs
+ * @param address The address to bind to; the InetAddress is either
+ * an IPv4 or IPv6 address.
+ * @throws IOException If binding fails; for example, if the port
+ * in the given InetSocketAddress is privileged, and the current
+ * process has insufficient privileges.
*/
- static native void connect(PlainSocketImpl socket, InetAddress addr,
- int port) throws IOException;
-
+ public void bind(InetSocketAddress address) throws IOException
+ {
+ InetAddress addr = address.getAddress();
+ if (addr instanceof Inet4Address)
+ {
+ bind (nfd.getNativeFD(), addr.getAddress(), address.getPort());
+ }
+ else if (addr instanceof Inet6Address)
+ bind6 (nfd.getNativeFD(), addr.getAddress(), address.getPort());
+ else
+ throw new SocketException ("unsupported address type");
+ }
+
/**
- * Binds to the specified port on the specified addr. Note that this addr
- * must represent a local IP address. **** How bind to INADDR_ANY? ****
- *
- * @param socket the socket object
- * @param addr the address to bind to
- * @param port the port number to bind to
+ * Native bind function for IPv4 addresses. The addr array must be
+ * exactly four bytes long.
+ *
+ * VMs without native support need not implement this.
*
- * @exception IOException If an error occurs
+ * @param fd The native file descriptor integer.
+ * @param addr The IPv4 address, in network byte order.
+ * @param port The port to bind to.
+ * @throws IOException
*/
- static native void bind(PlainSocketImpl socket, InetAddress addr, int port)
+ private static native void bind(int fd, byte[] addr, int port)
throws IOException;
-
+
/**
- * Starts listening for connections on a socket. The queueLen parameter
- * is how many pending connections will queue up waiting to be serviced
- * before being accepted. If the queue of pending requests exceeds this
- * number, additional connections will be refused.
- *
- * @param socket the socket object
- * @param queueLen the length of the pending connection queue
+ * Native bind function for IPv6 addresses. The addr array must be
+ * exactly sixteen bytes long.
*
- * @exception IOException if an error occurs
- */
- static native void listen(PlainSocketImpl socket, int queueLen)
- throws IOException;
-
- /**
- * Accepts a new connection on this socket.
+ * VMs without native support need not implement this.
*
- * @param socket the socket object
- * @param impl the socket object to accept this connection.
+ * @param fd The native file descriptor integer.
+ * @param addr The IPv6 address, in network byte order.
+ * @param port The port to bind to.
+ * @throws IOException
*/
- static native void accept(PlainSocketImpl socket, SocketImpl impl)
+ private static native void bind6(int fd, byte[] addr, int port)
throws IOException;
/**
- * Returns the number of bytes that the caller can read from this socket
- * without blocking.
- *
- * @param socket the socket object
- *
- * @return the number of readable bytes before blocking
- *
- * @throws IOException If an error occurs
- */
- static native int available(PlainSocketImpl socket) throws IOException;
-
- /**
- * Closes the socket. This will cause any InputStream or OutputStream
- * objects for this Socket to be closed as well.
- *
- * <p>
- * Note that if the SO_LINGER option is set on this socket, then the
- * operation could block.
- * </p>
- *
- * @param socket the socket object
+ * Listen on this socket for incoming connections.
*
- * @throws IOException if an error occurs
+ * @param backlog The backlog of connections.
+ * @throws IOException If listening fails.
+ * @see gnu.java.nio.VMChannel#accept()
*/
- static native void close(PlainSocketImpl socket) throws IOException;
-
+ public void listen(int backlog) throws IOException
+ {
+ listen(nfd.getNativeFD(), backlog);
+ }
+
/**
- * Internal method used by SocketInputStream for reading data from
- * the connection. Reads up to len bytes of data into the buffer
- * buf starting at offset bytes into the buffer.
- *
- * @param socket the socket object
+ * Native listen function. VMs without native support need not implement
+ * this.
*
- * @return the actual number of bytes read or -1 if end of stream.
- *
- * @throws IOException if an error occurs
+ * @param fd The file descriptor integer.
+ * @param backlog The listen backlog size.
+ * @throws IOException
*/
- static native int read(PlainSocketImpl socket, byte[] buf, int offset,
- int len) throws IOException;
+ private static native void listen(int fd, int backlog) throws IOException;
- /**
- * Internal method used by SocketInputStream for reading data from
- * the connection. Reads and returns one byte of data.
- *
- * @param socket the socket object
- *
- * @return read byte or -1 if end of stream.
- *
- * @throws IOException if an error occurs
- */
- static int read(PlainSocketImpl socket) throws IOException
+ public void join(InetAddress group) throws IOException
{
- byte[] buf = new byte[1];
- if (read(socket, buf, 0, 1) > 0)
- return buf[0] & 0xFF;
+ if (group instanceof Inet4Address)
+ join(nfd.getNativeFD(), group.getAddress());
+ else if (group instanceof Inet6Address)
+ join6(nfd.getNativeFD(), group.getAddress());
else
- return -1;
+ throw new IllegalArgumentException("unknown address type");
}
+
+ private static native void join(int fd, byte[] addr) throws IOException;
+
+ private static native void join6(int fd, byte[] addr) throws IOException;
+
+ public void leave(InetAddress group) throws IOException
+ {
+ if (group instanceof Inet4Address)
+ leave(nfd.getNativeFD(), group.getAddress());
+ else if (group instanceof Inet6Address)
+ leave6(nfd.getNativeFD(), group.getAddress());
+ else
+ throw new IllegalArgumentException("unknown address type");
+ }
+
+ private static native void leave(int fd, byte[] addr) throws IOException;
+
+ private static native void leave6(int fd, byte[] addr) throws IOException;
- /**
- * Internal method used by SocketOuputStream for writing data to
- * the connection. Writes up to len bytes of data from the buffer
- * <code>buf</code> starting at <cod>offset</code> bytes into the buffer.
- *
- * @param socket the socket object
- * @param buf the buffer to write to the stream
- * @param offset the start offset in the buffer
- * @param len the number of bytes to write
- *
- * @throws IOException if an error occurs
- */
- static native void write(PlainSocketImpl socket, byte[] buf, int offset,
- int len) throws IOException;
-
- /**
- * Internal method used by SocketOuputStream for writing data to
- * the connection. Writes exactly one byte to the socket.
- *
- * @param socket the socket object
- * @param data the byte to write to the socket
- *
- * @throws IOException if an error occurs
- */
- static void write(PlainSocketImpl socket, int data)
+ public void joinGroup(InetSocketAddress addr, NetworkInterface netif)
throws IOException
{
- write(socket, new byte[]{ (byte) data }, 0, 1);
+ InetAddress address = addr.getAddress();
+
+ if (address instanceof Inet4Address)
+ joinGroup(nfd.getNativeFD(), address.getAddress(),
+ netif != null ? netif.getName() : null);
+ else if (address instanceof Inet6Address)
+ joinGroup6(nfd.getNativeFD(), address.getAddress(),
+ netif != null ? netif.getName() : null);
+ else
+ throw new IllegalArgumentException("unknown address type");
}
-
- /**
- * Sets the input stream for this socket to the end of the stream. Any
- * attempts to read more bytes from the stream will return an EOF.
- *
- * @param socket the socket object
- *
- * @throws IOException if I/O errors occur
- */
- static native void shutdownInput(PlainSocketImpl socket) throws IOException;
-
- /**
- * Disables the output stream for this socket. Any attempt to write more
- * data to the socket will throw an IOException.
- *
- * @param socket the socket object
- *
- * @throws IOException if I/O errors occur
- */
- static native void shutdownOutput(PlainSocketImpl socket) throws IOException;
-
- /**
- * Connects to the remote socket address with a specified timeout.
- *
- * @param socket the socket object
- * @param address the remote address to connect to
- * @param timeout the timeout to use for this connect, 0 means infinite.
- *
- * @throws IOException if an error occurs
- */
- static synchronized void connect(PlainSocketImpl socket,
- SocketAddress address, int timeout)
+
+ private static native void joinGroup(int fd, byte[] addr, String ifname)
+ throws IOException;
+
+ private static native void joinGroup6(int fd, byte[] addr, String ifname)
+ throws IOException;
+
+ public void leaveGroup(InetSocketAddress addr, NetworkInterface netif)
throws IOException
{
- InetSocketAddress sockAddr = (InetSocketAddress) address;
- InetAddress addr = sockAddr.getAddress();
-
- if (addr == null)
- throw new UnknownHostException(sockAddr.getHostName());
-
- int port = sockAddr.getPort();
-
- if (timeout < 0)
- throw new IllegalArgumentException("negative timeout");
-
- Object oldTimeoutObj = null;
- try
- {
- oldTimeoutObj = getOption(socket, SocketOptions.SO_TIMEOUT);
- setOption(socket, SocketOptions.SO_TIMEOUT, new Integer(timeout));
- connect(socket, addr, port);
- }
- finally
- {
- if (oldTimeoutObj != null)
- setOption(socket, SocketOptions.SO_TIMEOUT, oldTimeoutObj);
- }
+ InetAddress address = addr.getAddress();
+ if (address instanceof Inet4Address)
+ leaveGroup(nfd.getNativeFD(), address.getAddress(),
+ netif != null ? netif.getName() : null);
+ else if (address instanceof Inet6Address)
+ leaveGroup6(nfd.getNativeFD(), address.getAddress(),
+ netif != null ? netif.getName() : null);
+ else
+ throw new IllegalArgumentException("unknown address type");
}
-
+
+ private static native void leaveGroup(int fd, byte[] addr, String ifname)
+ throws IOException;
+
+ private static native void leaveGroup6(int fd, byte[] addr, String ifname)
+ throws IOException;
+
+
+ public void shutdownInput() throws IOException
+ {
+ shutdownInput(nfd.getNativeFD());
+ }
+
+ private static native void shutdownInput(int native_fd) throws IOException;
+
+ public void shutdownOutput() throws IOException
+ {
+ shutdownOutput(nfd.getNativeFD());
+ }
+
+ private static native void shutdownOutput(int native_fd) throws IOException;
+
+ public void sendUrgentData(int data) throws IOException
+ {
+ sendUrgentData(nfd.getNativeFD(), data);
+ }
+
+ private static native void sendUrgentData(int natfive_fd, int data) throws IOException;
+
+ public void close() throws IOException
+ {
+ nfd.close();
+ }
+
+ // Inner classes.
+
/**
- * Send one byte of urgent data over the socket.
- *
- * @param socket the socket object
- * @param data the byte to send
+ * Our wrapper for the native file descriptor. In this implementation,
+ * it is a simple wrapper around {@link VMChannel.State}, to simplify
+ * management of the native state.
*/
- static void sendUrgendData(PlainSocketImpl socket, int data)
+ public final class State
{
- throw new InternalError ("PlainSocketImpl::sendUrgentData not implemented");
+ private VMChannel.State channelFd;
+
+ State()
+ {
+ channelFd = null;
+ }
+
+ public boolean isValid()
+ {
+ if (channelFd != null)
+ return channelFd.isValid();
+ return false;
+ }
+
+ public int getNativeFD() throws IOException
+ {
+ return channelFd.getNativeFD();
+ }
+
+ public void setChannelFD(final VMChannel.State nfd) throws IOException
+ {
+ if (this.channelFd != null && this.channelFd.isValid())
+ throw new IOException("file descriptor already initialized");
+ this.channelFd = nfd;
+ }
+
+ public void close() throws IOException
+ {
+ if (channelFd == null)
+ throw new IOException("invalid file descriptor");
+ channelFd.close();
+ }
+
+ protected void finalize() throws Throwable
+ {
+ try
+ {
+ if (isValid())
+ close();
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
}
-}
+} \ 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 fdea8ff62..ab09ef801 100644
--- a/vm/reference/gnu/java/nio/VMChannel.java
+++ b/vm/reference/gnu/java/nio/VMChannel.java
@@ -39,13 +39,22 @@ exception statement from your version. */
package gnu.java.nio;
import gnu.classpath.Configuration;
+import gnu.classpath.Pointer;
+import gnu.classpath.jdwp.exception.NotImplementedException;
import gnu.java.net.PlainSocketImpl;
import gnu.java.nio.PipeImpl.SinkChannelImpl;
import gnu.java.nio.PipeImpl.SourceChannelImpl;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
/**
* Native interface to support configuring of channel to run in a non-blocking
@@ -54,33 +63,43 @@ import java.nio.ByteBuffer;
* @author Michael Barker <mike@middlesoft.co.uk>
*
*/
-public class VMChannel
+public final class VMChannel
{
- private final int fd;
-
- private VMChannel(int fd)
- {
- this.fd = fd;
- }
+ /**
+ * Our reference implementation uses an integer to store the native
+ * file descriptor. Implementations without such support
+ */
+ private final State nfd;
- public static VMChannel getVMChannel(PlainSocketImpl socket)
- {
- return new VMChannel(socket.getNativeFD());
- }
+ private Kind kind;
- public static VMChannel getVMChannel(SourceChannelImpl source)
+ public VMChannel()
{
- return new VMChannel(source.getNativeFD());
+ // XXX consider adding security check here, so only Classpath
+ // code may create instances.
+ this.nfd = new State();
+ kind = Kind.OTHER;
}
- public static VMChannel getVMChannel(SinkChannelImpl sink)
+ /**
+ * This constructor is used by the POSIX reference implementation;
+ * other virtual machines need not support it.
+ *
+ * <strong>Important:</strong> do not call this in library code that is
+ * not specific to Classpath's reference implementation.
+ *
+ * @param native_fd The native file descriptor integer.
+ * @throws IOException
+ */
+ VMChannel(final int native_fd) throws IOException
{
- return new VMChannel(sink.getNativeFD());
+ this();
+ this.nfd.setNativeFD(native_fd);
}
- public static VMChannel getVMChannel(FileChannelImpl file)
+ public State getState()
{
- return new VMChannel(file.getNativeFD());
+ return nfd;
}
static
@@ -93,81 +112,151 @@ public class VMChannel
initIDs();
}
+ public static VMChannel getStdin() throws IOException
+ {
+ return new VMChannel(stdin_fd());
+ }
+
+ public static VMChannel getStdout() throws IOException
+ {
+ return new VMChannel(stdout_fd());
+ }
+
+ public static VMChannel getStderr() throws IOException
+ {
+ return new VMChannel(stderr_fd());
+ }
+
+ private static native int stdin_fd();
+ private static native int stdout_fd();
+ private static native int stderr_fd();
+
/**
* Set the file descriptor to have the required blocking
* setting.
*
- * @param fd
- * @param blocking
+ * @param blocking The blocking flag to set.
*/
- public native void setBlocking(int fd, boolean blocking);
+ public void setBlocking(boolean blocking) throws IOException
+ {
+ setBlocking(nfd.getNativeFD(), blocking);
+ }
+
+ private static native void setBlocking(int fd, boolean blocking)
+ throws IOException;
- public void setBlocking(boolean blocking)
+ public int available() throws IOException
{
- setBlocking(fd, blocking);
+ return available(nfd.getNativeFD());
}
+ private static native int available(int native_fd) throws IOException;
/**
* Reads a byte buffer directly using the supplied file descriptor.
- * Assumes that the buffer is a DirectBuffer.
*
- * @param fd Native file descriptor to read from.
* @param dst Direct Byte Buffer to read to.
* @return Number of bytes read.
* @throws IOException If an error occurs or dst is not a direct buffers.
*/
- native int read(int fd, ByteBuffer dst)
- throws IOException;
-
public int read(ByteBuffer dst)
throws IOException
{
- return read(fd, dst);
+ return read(nfd.getNativeFD(), dst);
}
+ private static native int read(int fd, ByteBuffer dst) throws IOException;
+
+ /**
+ * Read a single byte.
+ *
+ * @return The byte read, or -1 on end of file.
+ * @throws IOException
+ */
+ public int read() throws IOException
+ {
+ return read(nfd.getNativeFD());
+ }
+
+ private static native int read(int fd) throws IOException;
+
/**
* Reads into byte buffers directly using the supplied file descriptor.
* Assumes that the buffer list contains DirectBuffers. Will perform a
* scattering read.
*
- * @param fd Native file descriptor to read from.
* @param dsts An array direct byte buffers.
* @param offset Index of the first buffer to read to.
* @param length The number of buffers to read to.
* @return Number of bytes read.
* @throws IOException If an error occurs or the dsts are not direct buffers.
*/
- native long readScattering(int fd, ByteBuffer[] dsts, int offset, int length)
- throws IOException;
-
public long readScattering(ByteBuffer[] dsts, int offset, int length)
throws IOException
{
if (offset + length > dsts.length)
throw new IndexOutOfBoundsException("offset + length > dsts.length");
- return readScattering(fd, dsts, offset, length);
+ return readScattering(nfd.getNativeFD(), dsts, offset, length);
}
+ private static native long readScattering(int fd, ByteBuffer[] dsts,
+ int offset, int length)
+ throws IOException;
+
+ /**
+ * Receive a datagram on this channel, returning the host address
+ * that sent the datagram.
+ *
+ * @param dst Where to store the datagram.
+ * @return The host address that sent the datagram.
+ * @throws IOException
+ */
+ public SocketAddress receive(ByteBuffer dst) throws IOException
+ {
+ if (kind != Kind.SOCK_DGRAM)
+ throw new SocketException("not a datagram socket");
+ ByteBuffer hostPort = ByteBuffer.allocateDirect(18);
+ int hostlen = receive(nfd.getNativeFD(), dst, hostPort);
+ if (hostlen == 0)
+ return null;
+ if (hostlen == 4) // IPv4
+ {
+ byte[] addr = new byte[4];
+ hostPort.get(addr);
+ int port = hostPort.getShort() & 0xFFFF;
+ return new InetSocketAddress(Inet4Address.getByAddress(addr), port);
+ }
+ if (hostlen == 16) // IPv6
+ {
+ byte[] addr = new byte[16];
+ hostPort.get(addr);
+ int port = hostPort.getShort() & 0xFFFF;
+ return new InetSocketAddress(Inet6Address.getByAddress(addr), port);
+ }
+
+ throw new SocketException("host address received with invalid length: "
+ + hostlen);
+ }
+
+ private static native int receive (int fd, ByteBuffer dst, ByteBuffer address)
+ throws IOException;
+
/**
* Writes from a direct byte bufer using the supplied file descriptor.
* Assumes the buffer is a DirectBuffer.
*
- * @param fd
- * @param src
+ * @param src The source buffer.
* @return Number of bytes written.
* @throws IOException
*/
- native int write(int fd, ByteBuffer src)
- throws IOException;
-
- public int write(ByteBuffer src)
- throws IOException
+ public int write(ByteBuffer src) throws IOException
{
- return write(fd, src);
+ return write(nfd.getNativeFD(), src);
}
+ private native int write(int fd, ByteBuffer src) throws IOException;
+
/**
* Writes from byte buffers directly using the supplied file descriptor.
* Assumes the that buffer list constains DirectBuffers. Will perform
@@ -180,18 +269,448 @@ public class VMChannel
* @return Number of bytes written.
* @throws IOException
*/
- native long writeGathering(int fd, ByteBuffer[] srcs, int offset, int length)
- throws IOException;
-
public long writeGathering(ByteBuffer[] srcs, int offset, int length)
throws IOException
{
if (offset + length > srcs.length)
throw new IndexOutOfBoundsException("offset + length > srcs.length");
- return writeGathering(fd, srcs, offset, length);
+ return writeGathering(nfd.getNativeFD(), srcs, offset, length);
+ }
+
+ private native long writeGathering(int fd, ByteBuffer[] srcs,
+ int offset, int length)
+ throws IOException;
+
+ /**
+ * Send a datagram to the given address.
+ *
+ * @param src The source buffer.
+ * @param dst The destination address.
+ * @return The number of bytes written.
+ * @throws IOException
+ */
+ public int send(ByteBuffer src, InetSocketAddress dst)
+ throws IOException
+ {
+ InetAddress addr = dst.getAddress();
+ if (addr == null)
+ throw new NullPointerException();
+ if (addr instanceof Inet4Address)
+ return send(nfd.getNativeFD(), src, addr.getAddress(), dst.getPort());
+ else if (addr instanceof Inet6Address)
+ return send6(nfd.getNativeFD(), src, addr.getAddress(), dst.getPort());
+ else
+ throw new SocketException("unrecognized inet address type");
+ }
+
+ // Send to an IPv4 address.
+ private static native int send(int fd, ByteBuffer src, byte[] addr, int port)
+ throws IOException;
+
+ // Send to an IPv6 address.
+ private static native int send6(int fd, ByteBuffer src, byte[] addr, int port)
+ throws IOException;
+
+ /**
+ * Write a single byte.
+ *
+ * @param b The byte to write.
+ * @throws IOException
+ */
+ public void write(int b) throws IOException
+ {
+ write(nfd.getNativeFD(), b);
}
+ private static native void write(int fd, int b) throws IOException;
+
private native static void initIDs();
+ // Network (socket) specific methods.
+
+ /**
+ * Create a new socket. This method will initialize the native file
+ * descriptor state of this instance.
+ *
+ * @param stream Whether or not to create a streaming socket, or a datagram
+ * socket.
+ * @throws IOException If creating a new socket fails, or if this
+ * channel already has its native descriptor initialized.
+ */
+ public void initSocket(boolean stream) throws IOException
+ {
+ if (nfd.isValid())
+ throw new IOException("native FD already initialized");
+ if (stream)
+ kind = Kind.SOCK_STREAM;
+ else
+ kind = Kind.SOCK_DGRAM;
+ nfd.setNativeFD(socket(stream));
+ }
+
+ /**
+ * Create a new socket, returning the native file descriptor.
+ *
+ * @param stream Set to true for streaming sockets; false for datagrams.
+ * @return The native file descriptor.
+ * @throws IOException If creating the socket fails.
+ */
+ private static native int socket(boolean stream) throws IOException;
+
+ /**
+ * Connect the underlying socket file descriptor to the remote host.
+ *
+ * @param saddr The address to connect to.
+ * @param timeout The connect timeout to use for blocking connects.
+ * @return True if the connection succeeded; false if the file descriptor
+ * is in non-blocking mode and the connection did not immediately
+ * succeed.
+ * @throws IOException If an error occurs while connecting.
+ */
+ public boolean connect(InetSocketAddress saddr, int timeout)
+ throws IOException
+ {
+ InetAddress addr = saddr.getAddress();
+ if (addr instanceof Inet4Address)
+ return connect(nfd.getNativeFD(), addr.getAddress(), saddr.getPort(),
+ timeout);
+ if (addr instanceof Inet6Address)
+ return connect6(nfd.getNativeFD(), addr.getAddress(), saddr.getPort(),
+ timeout);
+ throw new IOException("unsupported internet address");
+ }
+
+ private static native boolean connect(int fd, byte[] addr, int port, int timeout)
+ throws IOException;
+
+ private static native boolean connect6(int fd, byte[] addr, int port, int timeout)
+ throws IOException;
+
+ /**
+ * Disconnect this channel, if it is a datagram socket. Disconnecting
+ * a datagram channel will disassociate it from any address, so the
+ * socket will remain open, but can send and receive datagrams from
+ * any address.
+ *
+ * @throws IOException If disconnecting this channel fails, or if this
+ * channel is not a datagram channel.
+ */
+ public void disconnect() throws IOException
+ {
+ if (kind != Kind.SOCK_DGRAM)
+ throw new IOException("can only disconnect datagram channels");
+ disconnect(nfd.getNativeFD());
+ }
+
+ private static native void disconnect(int fd) throws IOException;
+
+ public InetSocketAddress getLocalAddress() throws IOException
+ {
+ if (!nfd.isValid())
+ return null;
+ ByteBuffer name = ByteBuffer.allocateDirect(18);
+ int namelen = getsockname(nfd.getNativeFD(), name);
+ if (namelen == 0) // not bound
+ return null; // XXX return some wildcard?
+ if (namelen == 4)
+ {
+ byte[] addr = new byte[4];
+ name.get(addr);
+ int port = name.getShort() & 0xFFFF;
+ return new InetSocketAddress(Inet4Address.getByAddress(addr), port);
+ }
+ if (namelen == 16)
+ {
+ byte[] addr = new byte[16];
+ name.get(addr);
+ int port = name.getShort() & 0xFFFF;
+ return new InetSocketAddress(Inet6Address.getByAddress(addr), port);
+ }
+ throw new SocketException("invalid address length");
+ }
+
+ private static native int getsockname(int fd, ByteBuffer name)
+ throws IOException;
+
+ /**
+ * Returns the socket address of the remote peer this channel is connected
+ * to, or null if this channel is not yet connected.
+ *
+ * @return The peer address.
+ * @throws IOException
+ */
+ public InetSocketAddress getPeerAddress() throws IOException
+ {
+ if (!nfd.isValid())
+ return null;
+ ByteBuffer name = ByteBuffer.allocateDirect(18);
+ int namelen = getpeername (nfd.getNativeFD(), name);
+ if (namelen == 0) // not connected yet
+ return null;
+ if (namelen == 4) // IPv4
+ {
+ byte[] addr = new byte[4];
+ name.get(addr);
+ int port = name.getShort() & 0xFFFF;
+ return new InetSocketAddress(Inet4Address.getByAddress(addr), port);
+ }
+ else if (namelen == 16) // IPv6
+ {
+ byte[] addr = new byte[16];
+ name.get(addr);
+ int port = name.getShort() & 0xFFFF;
+ return new InetSocketAddress(Inet6Address.getByAddress(addr), port);
+ }
+ throw new SocketException("invalid address length");
+ }
+
+ /*
+ * The format here is the peer address, followed by the port number.
+ * The returned value is the length of the peer address; thus, there
+ * will be LEN + 2 valid bytes put into NAME.
+ */
+ private static native int getpeername(int fd, ByteBuffer name)
+ throws IOException;
+
+ /**
+ * Accept an incoming connection, returning a new VMChannel, or null
+ * if the channel is nonblocking and no connection is pending.
+ *
+ * @return The accepted connection, or null.
+ * @throws IOException If an IO error occurs.
+ */
+ public VMChannel accept() throws IOException
+ {
+ int new_fd = accept(nfd.getNativeFD());
+ if (new_fd == -1) // non-blocking accept had no pending connection
+ return null;
+ return new VMChannel(new_fd);
+ }
+
+ private static native int accept(int native_fd) throws IOException;
+
+ // File-specific methods.
+
+ /**
+ * Open a file at PATH, initializing the native state to operate on
+ * that open file.
+ *
+ * @param path The absolute file path.
+ * @throws IOException If the file cannot be opened, or if this
+ * channel was previously initialized.
+ */
+ public void openFile(String path, int mode) throws IOException
+ {
+ if (nfd.isValid() || nfd.isClosed())
+ throw new IOException("can't reinitialize this channel");
+ int fd = open(path, mode);
+ nfd.setNativeFD(fd);
+ kind = Kind.FILE;
+ }
+
+ private static native int open(String path, int mode) throws IOException;
+
+ public long position() throws IOException
+ {
+ if (kind != Kind.FILE)
+ throw new IOException("not a file");
+ return position(nfd.getNativeFD());
+ }
+
+ private static native long position(int fd) throws IOException;
+
+ public void seek(long pos) throws IOException
+ {
+ if (kind != Kind.FILE)
+ throw new IOException("not a file");
+ seek(nfd.getNativeFD(), pos);
+ }
+
+ private static native void seek(int fd, long pos) throws IOException;
+
+ public void truncate(long length) throws IOException
+ {
+ if (kind != Kind.FILE)
+ throw new IOException("not a file");
+ truncate(nfd.getNativeFD(), length);
+ }
+
+ private static native void truncate(int fd, long len) throws IOException;
+
+ public boolean lock(long pos, long len, boolean shared, boolean wait)
+ throws IOException
+ {
+ if (kind != Kind.FILE)
+ throw new IOException("not a file");
+ return lock(nfd.getNativeFD(), pos, len, shared, wait);
+ }
+
+ private static native boolean lock(int fd, long pos, long len,
+ boolean shared, boolean wait)
+ throws IOException;
+
+ public void unlock(long pos, long len) throws IOException
+ {
+ if (kind != Kind.FILE)
+ throw new IOException("not a file");
+ unlock(nfd.getNativeFD(), pos, len);
+ }
+
+ private static native void unlock(int fd, long pos, long len) throws IOException;
+
+ public long size() throws IOException
+ {
+ if (kind != Kind.FILE)
+ throw new IOException("not a file");
+ return size(nfd.getNativeFD());
+ }
+
+ private static native long size(int fd) throws IOException;
+
+ public MappedByteBuffer map(char mode, long position, int size)
+ throws IOException
+ {
+ if (kind != Kind.FILE)
+ throw new IOException("not a file");
+ return map(nfd.getNativeFD(), mode, position, size);
+ }
+
+ private static native MappedByteBuffer map(int fd, char mode,
+ long position, int size)
+ throws IOException;
+
+ public boolean flush(boolean metadata) throws IOException
+ {
+ if (kind != Kind.FILE)
+ throw new IOException("not a file");
+ return flush(nfd.getNativeFD(), metadata);
+ }
+
+ private static native boolean flush(int fd, boolean metadata) throws IOException;
+
+ // Close.
+
+ /**
+ * Close this socket. The socket is also automatically closed when this
+ * object is finalized.
+ *
+ * @throws IOException If closing the socket fails, or if this object has
+ * no open socket.
+ */
+ public void close() throws IOException
+ {
+ nfd.close();
+ }
+
+ static native void close(int native_fd) throws IOException;
+
+ // Inner classes.
+
+ /**
+ * A wrapper for a native file descriptor integer. This tracks the state
+ * of an open file descriptor, and ensures that
+ *
+ * This class need not be fully supported by virtual machines; if a
+ * virtual machine does not use integer file descriptors, or does and
+ * wishes to hide that, then the methods of this class may be stubbed out.
+ *
+ * System-specific classes that depend on access to native file descriptor
+ * integers SHOULD declare this fact.
+ */
+ public final class State
+ {
+ private int native_fd;
+ private boolean valid;
+ private boolean closed;
+
+ State()
+ {
+ native_fd = -1;
+ valid = false;
+ closed = false;
+ }
+
+ public boolean isValid()
+ {
+ return valid;
+ }
+
+ public boolean isClosed()
+ {
+ return closed;
+ }
+
+ public int getNativeFD() throws IOException
+ {
+ if (!valid)
+ throw new IOException("invalid file descriptor");
+ return native_fd;
+ }
+
+ void setNativeFD(final int native_fd) throws IOException
+ {
+ if (valid)
+ throw new IOException("file descriptor already initialized");
+ this.native_fd = native_fd;
+ valid = true;
+ }
+
+ public void close() throws IOException
+ {
+ if (!valid)
+ throw new IOException("invalid file descriptor");
+ try
+ {
+ VMChannel.close(native_fd);
+ }
+ finally
+ {
+ valid = false;
+ closed = true;
+ }
+ }
+
+ public String toString()
+ {
+ if (!valid)
+ return "<<invalid>>";
+ if (closed)
+ return "<<closed>>";
+ return String.valueOf(native_fd);
+ }
+
+ protected void finalize() throws Throwable
+ {
+ try
+ {
+ if (valid)
+ close();
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+ }
+
+ /**
+ * An enumeration of possible kinds of channel.
+ */
+ static class Kind // XXX enum
+ {
+ /** A streaming (TCP) socket. */
+ static final Kind SOCK_STREAM = new Kind();
+
+ /** A datagram (UDP) socket. */
+ static final Kind SOCK_DGRAM = new Kind();
+
+ /** A file. */
+ static final Kind FILE = new Kind();
+
+ /** Something else; not a socket or file. */
+ static final Kind OTHER = new Kind();
+
+ private Kind() { }
+ }
}
diff --git a/vm/reference/gnu/java/nio/VMPipe.java b/vm/reference/gnu/java/nio/VMPipe.java
index 11dd2aa7b..3fe363155 100644
--- a/vm/reference/gnu/java/nio/VMPipe.java
+++ b/vm/reference/gnu/java/nio/VMPipe.java
@@ -58,7 +58,24 @@ final class VMPipe
System.loadLibrary ("javanio");
}
}
-
- static native void init(PipeImpl self, SelectorProvider provider)
- throws IOException;
+
+ /**
+ * Create a pipe, consisting of a readable VMChannel and a writable
+ * VMChannel. The readable channel is returned is the first element
+ * of the array, and the writable in the second.
+ *
+ * @return A pair of VMChannels; the first readable, the second
+ * writable.
+ * @throws IOException If the pipe cannot be created.
+ */
+ static VMChannel[] pipe() throws IOException
+ {
+ VMChannel[] pipe = new VMChannel[2];
+ int[] fds = pipe0();
+ pipe[0] = new VMChannel(fds[0]);
+ pipe[1] = new VMChannel(fds[1]);
+ return pipe;
+ }
+
+ private static native int[] pipe0() throws IOException;
}
diff --git a/vm/reference/java/net/VMNetworkInterface.java b/vm/reference/java/net/VMNetworkInterface.java
index 47f803246..7a29f4ee3 100644
--- a/vm/reference/java/net/VMNetworkInterface.java
+++ b/vm/reference/java/net/VMNetworkInterface.java
@@ -40,6 +40,9 @@ package java.net;
import gnu.classpath.Configuration;
+import java.nio.ByteBuffer;
+import java.util.HashSet;
+import java.util.Set;
import java.util.Vector;
/**
@@ -54,22 +57,50 @@ import java.util.Vector;
*/
final class VMNetworkInterface
{
+ String name;
+ Set addresses;
+
+ VMNetworkInterface(String name)
+ {
+ this.name = name;
+ addresses = new HashSet();
+ }
+
static
- {
- if (Configuration.INIT_LOAD_LIBRARY)
- System.loadLibrary("javanet");
- }
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ System.loadLibrary("javanet");
+
+ initIds();
+ }
+
+ private static native void initIds();
/**
- * Returns a Vector of InetAddresses. The returned value will be
- * 'condensed', meaning that all elements with the same interface
- * name will be collapesed into one InetAddress for that name
- * containing all addresses before the returning the result to the
- * user. This means the native method can be implemented in a naive
- * way mapping each address/interface to a name even if that means
- * that the Vector contains multiple InetAddresses with the same
- * interface name.
+ * Return a list of VM network interface objects.
+ *
+ * @return The list of network interfaces.
+ * @throws SocketException
*/
- public static native Vector getInterfaces()
+ public static native VMNetworkInterface[] getVMInterfaces()
throws SocketException;
+
+ private void addAddress(ByteBuffer addr)
+ throws SocketException, UnknownHostException
+ {
+ if (addr.remaining() == 4)
+ {
+ byte[] ipv4 = new byte[4];
+ addr.get(ipv4);
+ addresses.add(Inet4Address.getByAddress(ipv4));
+ }
+ else if (addr.remaining() == 16)
+ {
+ byte[] ipv6 = new byte[16];
+ addr.get(ipv6);
+ addresses.add(Inet6Address.getByAddress(ipv6));
+ }
+ else
+ throw new SocketException("invalid interface address");
+ }
}
diff --git a/vm/reference/java/nio/channels/VMChannels.java b/vm/reference/java/nio/channels/VMChannels.java
index e58d7fbf9..c833b6eec 100644
--- a/vm/reference/java/nio/channels/VMChannels.java
+++ b/vm/reference/java/nio/channels/VMChannels.java
@@ -40,7 +40,7 @@ package java.nio.channels;
import gnu.java.nio.ChannelInputStream;
import gnu.java.nio.ChannelOutputStream;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
import java.io.FileInputStream;
import java.io.FileOutputStream;