diff options
author | jfrijters <jfrijters> | 2011-07-15 13:05:26 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2011-07-15 13:05:26 +0400 |
commit | 20464c682cbc4ab4b937774b1872928179870d74 (patch) | |
tree | 0df9c343c8ac6cb93ac55eec6e836a06e414b267 /openjdk/sun/nio/ch | |
parent | afeabe4188bd04bcfc74b141664c294fc57c4b0a (diff) |
Updated bulk of java.nio to OpenJDK 7.
Diffstat (limited to 'openjdk/sun/nio/ch')
-rw-r--r-- | openjdk/sun/nio/ch/DatagramChannelImpl.java | 465 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/DefaultAsynchronousChannelProvider.java | 5 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/FileChannelImpl.java | 19 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/IOUtil.java | 134 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/Net.java | 627 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/ServerSocketChannelImpl.java | 443 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/SocketChannelImpl.java | 1089 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/SocketDispatcher.java | 77 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/SocketOptionRegistry.java | 86 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/Util.java | 38 |
10 files changed, 822 insertions, 2161 deletions
diff --git a/openjdk/sun/nio/ch/DatagramChannelImpl.java b/openjdk/sun/nio/ch/DatagramChannelImpl.java index 72f62adf..fb6f6f8f 100644 --- a/openjdk/sun/nio/ch/DatagramChannelImpl.java +++ b/openjdk/sun/nio/ch/DatagramChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,18 +25,13 @@ package sun.nio.ch; -import ikvm.internal.NotYetImplementedError; - import java.io.FileDescriptor; import java.io.IOException; import java.net.*; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.channels.spi.*; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.lang.ref.SoftReference; +import java.util.*; import sun.net.ResourceManager; @@ -55,8 +50,15 @@ class DatagramChannelImpl private static final int IOC_VENDOR = 0x18000000; private static final int SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; + // Used to make native read and write calls + private static NativeDispatcher nd = new SocketDispatcher(); + // Our file descriptor - FileDescriptor fd = null; + private final FileDescriptor fd; + + // fd value needed for dev/poll. This value will remain valid + // even after the value in the file descriptor object has been set to -1 + private final int fdVal; // The protocol family of the socket private final ProtocolFamily family; @@ -67,8 +69,8 @@ class DatagramChannelImpl // Cached InetAddress and port for unconnected DatagramChannels // used by receive0 - private InetAddress cachedSenderInetAddress = null; - private int cachedSenderPort = 0; + private InetAddress cachedSenderInetAddress; + private int cachedSenderPort; // Lock held by current reading or connecting thread private final Object readLock = new Object(); @@ -84,20 +86,20 @@ class DatagramChannelImpl // State (does not necessarily increase monotonically) private static final int ST_UNINITIALIZED = -1; - private static int ST_UNCONNECTED = 0; - private static int ST_CONNECTED = 1; + private static final int ST_UNCONNECTED = 0; + private static final int ST_CONNECTED = 1; private static final int ST_KILLED = 2; private int state = ST_UNINITIALIZED; // Binding - private SocketAddress localAddress = null; - SocketAddress remoteAddress = null; - - // Options - private SocketOpts.IP options = null; + private SocketAddress localAddress; + private SocketAddress remoteAddress; // Our socket adaptor, if any - private DatagramSocket socket = null; + private DatagramSocket socket; + + // Multicast support + private MembershipRegistry registry; // -- End of fields protected by stateLock @@ -109,8 +111,9 @@ class DatagramChannelImpl ResourceManager.beforeUdpCreate(); try { this.family = Net.isIPv6Available() ? - StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; - this.fd = Net.socket(false); + StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + this.fd = Net.socket(family, false); + this.fdVal = IOUtil.fdVal(fd); this.state = ST_UNCONNECTED; try { @@ -128,11 +131,11 @@ class DatagramChannelImpl } public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family) - throws IOException + throws IOException { super(sp); if ((family != StandardProtocolFamily.INET) && - (family != StandardProtocolFamily.INET6)) + (family != StandardProtocolFamily.INET6)) { if (family == null) throw new NullPointerException("'family' is null"); @@ -145,7 +148,18 @@ class DatagramChannelImpl } } this.family = family; - throw new NotYetImplementedError(); //TODO JDK7 + this.fd = Net.socket(family, false); + this.fdVal = IOUtil.fdVal(fd); + this.state = ST_UNCONNECTED; + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + fd.getSocket().IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); + } + catch (cli.System.Net.Sockets.SocketException x) + { + throw SocketUtil.convertSocketExceptionToIOException(x); + } } public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd) @@ -153,9 +167,11 @@ class DatagramChannelImpl { super(sp); this.family = Net.isIPv6Available() ? - StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; this.fd = fd; + this.fdVal = IOUtil.fdVal(fd); this.state = ST_UNCONNECTED; + this.localAddress = Net.localAddress(fd); } public DatagramSocket socket() { @@ -166,6 +182,7 @@ class DatagramChannelImpl } } + @Override public SocketAddress getLocalAddress() throws IOException { synchronized (stateLock) { if (!isOpen()) @@ -174,6 +191,7 @@ class DatagramChannelImpl } } + @Override public SocketAddress getRemoteAddress() throws IOException { synchronized (stateLock) { if (!isOpen()) @@ -182,6 +200,7 @@ class DatagramChannelImpl } } + @Override public <T> DatagramChannel setOption(SocketOption<T> name, T value) throws IOException { @@ -235,6 +254,7 @@ class DatagramChannelImpl } } + @Override @SuppressWarnings("unchecked") public <T> T getOption(SocketOption<T> name) throws IOException @@ -307,6 +327,7 @@ class DatagramChannelImpl } } + @Override public final Set<SocketOption<?>> supportedOptions() { return DefaultOptionsHolder.defaultOptions; } @@ -325,9 +346,9 @@ class DatagramChannelImpl throw new NullPointerException(); synchronized (readLock) { ensureOpen(); - // If socket is not bound then behave as if nothing received - if (!isBound()) // ## NotYetBoundException ?? - return null; + // Socket was not bound before attempting receive + if (localAddress() == null) + bind(null); int n = 0; ByteBuffer bb = null; try { @@ -418,6 +439,12 @@ class DatagramChannelImpl do { n = sendImpl(src, isa); } while ((n == IOStatus.INTERRUPTED) && isOpen()); + + synchronized (stateLock) { + if (isOpen() && (localAddress == null)) { + localAddress = Net.localAddress(fd); + } + } return IOStatus.normalize(n); } finally { writerThread = 0; @@ -443,7 +470,7 @@ class DatagramChannelImpl return 0; readerThread = NativeThread.current(); do { - n = readImpl(buf); + n = IOUtil.read(fd, buf, -1, nd, readLock); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -454,9 +481,11 @@ class DatagramChannelImpl } } - private long read0(ByteBuffer[] bufs) throws IOException { - if (bufs == null) - throw new NullPointerException(); + public long read(ByteBuffer[] dsts, int offset, int length) + throws IOException + { + if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) + throw new IndexOutOfBoundsException(); synchronized (readLock) { synchronized (stateLock) { ensureOpen(); @@ -470,7 +499,7 @@ class DatagramChannelImpl return 0; readerThread = NativeThread.current(); do { - n = readImpl(bufs); + n = IOUtil.read(fd, dsts, offset, length, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -481,15 +510,6 @@ class DatagramChannelImpl } } - public long read(ByteBuffer[] dsts, int offset, int length) - throws IOException - { - if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) - throw new IndexOutOfBoundsException(); - // ## Fix IOUtil.write so that we can avoid this array copy - return read0(Util.subsequence(dsts, offset, length)); - } - public int write(ByteBuffer buf) throws IOException { if (buf == null) throw new NullPointerException(); @@ -506,7 +526,7 @@ class DatagramChannelImpl return 0; writerThread = NativeThread.current(); do { - n = writeImpl(buf); + n = IOUtil.write(fd, buf, -1, nd, writeLock); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -517,9 +537,11 @@ class DatagramChannelImpl } } - private long write0(ByteBuffer[] bufs) throws IOException { - if (bufs == null) - throw new NullPointerException(); + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException + { + if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) + throw new IndexOutOfBoundsException(); synchronized (writeLock) { synchronized (stateLock) { ensureOpen(); @@ -533,7 +555,7 @@ class DatagramChannelImpl return 0; writerThread = NativeThread.current(); do { - n = writeImpl(bufs); + n = IOUtil.write(fd, srcs, offset, length, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -544,55 +566,12 @@ class DatagramChannelImpl } } - public long write(ByteBuffer[] srcs, int offset, int length) - throws IOException - { - if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) - throw new IndexOutOfBoundsException(); - // ## Fix IOUtil.write so that we can avoid this array copy - return write0(Util.subsequence(srcs, offset, length)); - } - protected void implConfigureBlocking(boolean block) throws IOException { IOUtil.configureBlocking(fd, block); } - public SocketOpts options() { - synchronized (stateLock) { - if (options == null) { - SocketOptsImpl.Dispatcher d - = new SocketOptsImpl.Dispatcher() { - int getInt(int opt) throws IOException { - return Net.getIntOption(fd, opt); - } - void setInt(int opt, int arg) - throws IOException - { - Net.setIntOption(fd, opt, arg); - } - }; - options = new SocketOptsImpl.IP(d); - } - return options; - } - } - - public boolean isBound() { - return Net.localPortNumber(fd) != 0; - } - public SocketAddress localAddress() { synchronized (stateLock) { - if (isConnected() && (localAddress == null)) { - // Socket was not bound before connecting, - // so ask what the address turned out to be - localAddress = Net.localAddress(fd); - } - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - InetSocketAddress isa = (InetSocketAddress)localAddress; - sm.checkConnect(isa.getAddress().getHostAddress(), -1); - } return localAddress; } } @@ -603,18 +582,32 @@ class DatagramChannelImpl } } + @Override public DatagramChannel bind(SocketAddress local) throws IOException { synchronized (readLock) { synchronized (writeLock) { synchronized (stateLock) { ensureOpen(); - if (isBound()) + if (localAddress != null) throw new AlreadyBoundException(); - InetSocketAddress isa = Net.checkAddress(local); + InetSocketAddress isa; + if (local == null) { + isa = new InetSocketAddress(0); + } else { + isa = Net.checkAddress(local); + + // only Inet4Address allowed with IPv4 socket + if (family == StandardProtocolFamily.INET) { + InetAddress addr = isa.getAddress(); + if (!(addr instanceof Inet4Address)) + throw new UnsupportedAddressTypeException(); + } + } SecurityManager sm = System.getSecurityManager(); - if (sm != null) + if (sm != null) { sm.checkListen(isa.getPort()); - Net.bind(fd, isa.getAddress(), isa.getPort()); + } + Net.bind(family, fd, isa.getAddress(), isa.getPort()); localAddress = Net.localAddress(fd); } } @@ -638,7 +631,6 @@ class DatagramChannelImpl } public DatagramChannel connect(SocketAddress sa) throws IOException { - int trafficClass = 0; int localPort = 0; synchronized(readLock) { @@ -672,6 +664,9 @@ class DatagramChannelImpl sender = isa; cachedSenderInetAddress = isa.getAddress(); cachedSenderPort = isa.getPort(); + + // set or refresh local address + localAddress = Net.localAddress(fd); } } } @@ -692,6 +687,9 @@ class DatagramChannelImpl disconnect0(fd); remoteAddress = null; state = ST_UNCONNECTED; + + // refresh local address + localAddress = Net.localAddress(fd); } } } @@ -707,9 +705,94 @@ class DatagramChannelImpl InetAddress source) throws IOException { - throw new NotYetImplementedError(); //TODO JDK7 + if (!group.isMulticastAddress()) + throw new IllegalArgumentException("Group not a multicast address"); + + // check multicast address is compatible with this socket + if (group instanceof Inet4Address) { + if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group()) + throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group"); + } else if (group instanceof Inet6Address) { + if (family != StandardProtocolFamily.INET6) + throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group"); + } else { + throw new IllegalArgumentException("Address type not supported"); + } + + // check source address + if (source != null) { + if (source.isAnyLocalAddress()) + throw new IllegalArgumentException("Source address is a wildcard address"); + if (source.isMulticastAddress()) + throw new IllegalArgumentException("Source address is multicast address"); + if (source.getClass() != group.getClass()) + throw new IllegalArgumentException("Source address is different type to group"); + } + + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkMulticast(group); + + synchronized (stateLock) { + if (!isOpen()) + throw new ClosedChannelException(); + + // check the registry to see if we are already a member of the group + if (registry == null) { + registry = new MembershipRegistry(); + } else { + // return existing membership key + MembershipKey key = registry.checkMembership(group, interf, source); + if (key != null) + return key; + } + + MembershipKeyImpl key; + if ((family == StandardProtocolFamily.INET6) && + ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group())) + { + int index = interf.getIndex(); + if (index == -1) + throw new IOException("Network interface cannot be identified"); + + // need multicast and source address as byte arrays + byte[] groupAddress = Net.inet6AsByteArray(group); + byte[] sourceAddress = (source == null) ? null : + Net.inet6AsByteArray(source); + + // join the group + int n = Net.join6(fd, groupAddress, index, sourceAddress); + if (n == IOStatus.UNAVAILABLE) + throw new UnsupportedOperationException(); + + key = new MembershipKeyImpl.Type6(this, group, interf, source, + groupAddress, index, sourceAddress); + + } else { + // need IPv4 address to identify interface + Inet4Address target = Net.anyInet4Address(interf); + if (target == null) + throw new IOException("Network interface not configured for IPv4"); + + int groupAddress = Net.inet4AsInt(group); + int targetAddress = Net.inet4AsInt(target); + int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source); + + // join the group + int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress); + if (n == IOStatus.UNAVAILABLE) + throw new UnsupportedOperationException(); + + key = new MembershipKeyImpl.Type4(this, group, interf, source, + groupAddress, targetAddress, sourceAddress); + } + + registry.add(key); + return key; + } } + @Override public MembershipKey join(InetAddress group, NetworkInterface interf) throws IOException @@ -717,6 +800,7 @@ class DatagramChannelImpl return innerJoin(group, interf, null); } + @Override public MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source) @@ -726,11 +810,113 @@ class DatagramChannelImpl throw new NullPointerException("source address is null"); return innerJoin(group, interf, source); } - + + // package-private + void drop(MembershipKeyImpl key) { + assert key.channel() == this; + + synchronized (stateLock) { + if (!key.isValid()) + return; + + try { + if (key instanceof MembershipKeyImpl.Type6) { + MembershipKeyImpl.Type6 key6 = + (MembershipKeyImpl.Type6)key; + Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source()); + } else { + MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key; + Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(), + key4.source()); + } + } catch (IOException ioe) { + // should not happen + throw new AssertionError(ioe); + } + + key.invalidate(); + registry.remove(key); + } + } + + /** + * Block datagrams from given source if a memory to receive all + * datagrams. + */ + void block(MembershipKeyImpl key, InetAddress source) + throws IOException + { + assert key.channel() == this; + assert key.sourceAddress() == null; + + synchronized (stateLock) { + if (!key.isValid()) + throw new IllegalStateException("key is no longer valid"); + if (source.isAnyLocalAddress()) + throw new IllegalArgumentException("Source address is a wildcard address"); + if (source.isMulticastAddress()) + throw new IllegalArgumentException("Source address is multicast address"); + if (source.getClass() != key.group().getClass()) + throw new IllegalArgumentException("Source address is different type to group"); + + int n; + if (key instanceof MembershipKeyImpl.Type6) { + MembershipKeyImpl.Type6 key6 = + (MembershipKeyImpl.Type6)key; + n = Net.block6(fd, key6.groupAddress(), key6.index(), + Net.inet6AsByteArray(source)); + } else { + MembershipKeyImpl.Type4 key4 = + (MembershipKeyImpl.Type4)key; + n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(), + Net.inet4AsInt(source)); + } + if (n == IOStatus.UNAVAILABLE) { + // ancient kernel + throw new UnsupportedOperationException(); + } + } + } + + /** + * Unblock given source. + */ + void unblock(MembershipKeyImpl key, InetAddress source) { + assert key.channel() == this; + assert key.sourceAddress() == null; + + synchronized (stateLock) { + if (!key.isValid()) + throw new IllegalStateException("key is no longer valid"); + + try { + if (key instanceof MembershipKeyImpl.Type6) { + MembershipKeyImpl.Type6 key6 = + (MembershipKeyImpl.Type6)key; + Net.unblock6(fd, key6.groupAddress(), key6.index(), + Net.inet6AsByteArray(source)); + } else { + MembershipKeyImpl.Type4 key4 = + (MembershipKeyImpl.Type4)key; + Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(), + Net.inet4AsInt(source)); + } + } catch (IOException ioe) { + // should not happen + throw new AssertionError(ioe); + } + } + } + protected void implCloseSelectableChannel() throws IOException { synchronized (stateLock) { - closeImpl(); + nd.preClose(fd); ResourceManager.afterUdpClose(); + + // if member of mulitcast group then invalidate all keys + if (registry != null) + registry.invalidateAll(); + long th; if ((th = readerThread) != 0) NativeThread.signal(th); @@ -750,7 +936,7 @@ class DatagramChannelImpl return; } assert !isOpen() && !isRegistered(); - closeImpl(); + nd.close(fd); state = ST_KILLED; } } @@ -818,30 +1004,12 @@ class DatagramChannelImpl } public int getFDVal() { - throw new Error(); + return fdVal; } // -- Native methods -- - private void closeImpl() throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - fd.getSocket().Close(); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - private static void disconnect0(FileDescriptor fd) throws IOException { try @@ -969,67 +1137,4 @@ class DatagramChannelImpl throw new SocketException("Socket is closed"); } } - - private int readImpl(ByteBuffer bb) throws IOException - { - return receive0(bb); - } - - private long readImpl(ByteBuffer[] bb) throws IOException - { - // This is a rather lame implementation. On .NET 2.0 we could make this more - // efficient by using the IList<ArraySegment<byte>> overload of Socket.Send() - long size = 0; - for (int i = 0; i < bb.length; i++) - { - size += bb[i].remaining(); - } - // UDP has a maximum packet size of 64KB - byte[] buf = new byte[(int)Math.min(65536, size)]; - int n = receive0(ByteBuffer.wrap(buf)); - if (n <= 0) - { - return n; - } - for (int i = 0, pos = 0; i < bb.length && pos < buf.length; i++) - { - int len = Math.min(bb[i].remaining(), buf.length - pos); - bb[i].put(buf, pos, len); - pos += len; - } - return n; - } - - private int writeImpl(ByteBuffer bb) throws IOException - { - return sendImpl(bb, (InetSocketAddress)remoteAddress); - } - - private long writeImpl(ByteBuffer[] bb) throws IOException - { - // This is a rather lame implementation. On .NET 2.0 we could make this more - // efficient by using the IList<ArraySegment<byte>> overload of Socket.Send() - long totalWritten = 0; - for (int i = 0; i < bb.length; i++) - { - try - { - int len = writeImpl(bb[i]); - if (len < 0) - { - return totalWritten > 0 ? totalWritten : len; - } - totalWritten += len; - } - catch (IOException x) - { - if (totalWritten > 0) - { - return totalWritten; - } - throw x; - } - } - return totalWritten; - } } diff --git a/openjdk/sun/nio/ch/DefaultAsynchronousChannelProvider.java b/openjdk/sun/nio/ch/DefaultAsynchronousChannelProvider.java index 40448226..e2310f73 100644 --- a/openjdk/sun/nio/ch/DefaultAsynchronousChannelProvider.java +++ b/openjdk/sun/nio/ch/DefaultAsynchronousChannelProvider.java @@ -25,8 +25,6 @@ package sun.nio.ch; -import ikvm.internal.NotYetImplementedError; - import java.nio.channels.spi.AsynchronousChannelProvider; /** @@ -40,7 +38,6 @@ public class DefaultAsynchronousChannelProvider { * Returns the default AsynchronousChannelProvider. */ public static AsynchronousChannelProvider create() { - //return new WindowsAsynchronousChannelProvider(); - throw new NotYetImplementedError(); + throw new ikvm.internal.NotYetImplementedError(); } } diff --git a/openjdk/sun/nio/ch/FileChannelImpl.java b/openjdk/sun/nio/ch/FileChannelImpl.java index d34e1c1a..d26fdb3f 100644 --- a/openjdk/sun/nio/ch/FileChannelImpl.java +++ b/openjdk/sun/nio/ch/FileChannelImpl.java @@ -66,9 +66,6 @@ public class FileChannelImpl // Memory allocation size for mapping buffers private static final long allocationGranularity = 64 * 1024; // HACK we're using a hard coded value here that works on all mainstream platforms - // Cached field for MappedByteBuffer.isAMappedBuffer - private static Field isAMappedBufferField; - // File descriptor private FileDescriptor fd; @@ -602,10 +599,12 @@ public class FileChannelImpl } if (size == 0) { addr = 0; + // a valid file descriptor is not required + FileDescriptor dummy = new FileDescriptor(); if ((!writable) || (imode == MAP_RO)) - return Util.newMappedByteBufferR(0, 0, null); + return Util.newMappedByteBufferR(0, 0, dummy, null); else - return Util.newMappedByteBuffer(0, 0, null); + return Util.newMappedByteBuffer(0, 0, dummy, null); } int pagePosition = (int)(position % allocationGranularity); @@ -636,9 +635,9 @@ public class FileChannelImpl int isize = (int)size; Unmapper um = new Unmapper(addr, size + pagePosition); if ((!writable) || (imode == MAP_RO)) - return Util.newMappedByteBufferR(isize, addr + pagePosition, um); + return Util.newMappedByteBufferR(isize, addr + pagePosition, fd, um); else - return Util.newMappedByteBuffer(isize, addr + pagePosition, um); + return Util.newMappedByteBuffer(isize, addr + pagePosition, fd, um); } finally { end(IOStatus.checkAll(addr)); } @@ -1471,10 +1470,4 @@ public class FileChannelImpl { return fd.length(); } - - static { - isAMappedBufferField = Reflect.lookupField("java.nio.MappedByteBuffer", - "isAMappedBuffer"); - } - } diff --git a/openjdk/sun/nio/ch/IOUtil.java b/openjdk/sun/nio/ch/IOUtil.java index 9d26d6ef..eb413d4e 100644 --- a/openjdk/sun/nio/ch/IOUtil.java +++ b/openjdk/sun/nio/ch/IOUtil.java @@ -31,6 +31,7 @@ import java.net.*; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.channels.spi.*; +import cli.System.Net.Sockets.SocketFlags; /** @@ -58,7 +59,138 @@ class IOUtil { static void configureBlocking(FileDescriptor fd, boolean blocking) throws IOException { - Net.configureBlocking(fd, blocking); + fd.setSocketBlocking(blocking); } + // this is a dummy method to allow us to use unmodified socket channel impls + static int fdVal(FileDescriptor fd) + { + return 0xbadc0de; + } + + static int read(FileDescriptor fd, ByteBuffer dst, long position, + NativeDispatcher nd, Object lock) + throws IOException + { + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + if (position != -1) + throw new ikvm.internal.NotYetImplementedError(); + + if (dst.hasArray()) + { + byte[] buf = dst.array(); + int len = readImpl(fd, buf, dst.arrayOffset() + dst.position(), dst.remaining()); + if (len > 0) + { + dst.position(dst.position() + len); + } + return len; + } + else + { + byte[] buf = new byte[dst.remaining()]; + int len = readImpl(fd, buf, 0, buf.length); + if (len > 0) + { + dst.put(buf, 0, len); + } + return len; + } + } + + private static int readImpl(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException + { + if (length == 0) + { + return 0; + } + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + int read = fd.getSocket().Receive(buf, offset, length, SocketFlags.wrap(SocketFlags.None)); + return read == 0 ? IOStatus.EOF : read; + } + catch (cli.System.Net.Sockets.SocketException x) + { + if (x.get_ErrorCode() == SocketUtil.WSAESHUTDOWN) + { + // the socket was shutdown, so we have to return EOF + return IOStatus.EOF; + } + else if (x.get_ErrorCode() == SocketUtil.WSAEWOULDBLOCK) + { + // nothing to read and would block + return IOStatus.UNAVAILABLE; + } + throw SocketUtil.convertSocketExceptionToIOException(x); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new SocketException("Socket is closed"); + } + } + + static native long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, NativeDispatcher nd) + throws IOException; + + static int write(FileDescriptor fd, ByteBuffer src, long position, + NativeDispatcher nd, Object lock) + throws IOException + { + if (src.hasArray()) + { + byte[] buf = src.array(); + int len = writeImpl(fd, buf, src.arrayOffset() + src.position(), src.remaining()); + if (len > 0) + { + src.position(src.position() + len); + } + return len; + } + else + { + int pos = src.position(); + byte[] buf = new byte[src.remaining()]; + src.get(buf); + int len = writeImpl(fd, buf, 0, buf.length); + if (len > 0) + { + src.position(pos + len); + } + return len; + } + } + + private static int writeImpl(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException + { + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + return fd.getSocket().Send(buf, offset, length, SocketFlags.wrap(SocketFlags.None)); + } + catch (cli.System.Net.Sockets.SocketException x) + { + if (x.get_ErrorCode() == SocketUtil.WSAEWOULDBLOCK) + { + return IOStatus.UNAVAILABLE; + } + throw SocketUtil.convertSocketExceptionToIOException(x); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new SocketException("Socket is closed"); + } + } + + static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd) + throws IOException + { + return write(fd, bufs, 0, bufs.length, nd); + } + + static native long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, NativeDispatcher nd) + throws IOException; } diff --git a/openjdk/sun/nio/ch/Net.java b/openjdk/sun/nio/ch/Net.java index 9022d05e..71ae5436 100644 --- a/openjdk/sun/nio/ch/Net.java +++ b/openjdk/sun/nio/ch/Net.java @@ -25,29 +25,14 @@ package sun.nio.ch; -import cli.System.Net.IPAddress; -import cli.System.Net.IPEndPoint; -import cli.System.Net.Sockets.LingerOption; -import cli.System.Net.Sockets.SelectMode; -import cli.System.Net.Sockets.SocketOptionName; -import cli.System.Net.Sockets.SocketOptionLevel; -import cli.System.Net.Sockets.SocketFlags; -import cli.System.Net.Sockets.SocketType; -import cli.System.Net.Sockets.ProtocolType; -import cli.System.Net.Sockets.AddressFamily; -import cli.System.Net.Sockets.SocketShutdown; -import ikvm.internal.NotYetImplementedError; -import ikvm.lang.CIL; import java.io.*; import java.net.*; -import java.nio.ByteBuffer; import java.nio.channels.*; import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; - class Net { // package-private private Net() { } @@ -59,390 +44,40 @@ class Net { // package-private } }; + // -- Miscellaneous utilities -- + + private static volatile boolean checkedIPv6 = false; + private static volatile boolean isIPv6Available; + /** * Tells whether dual-IPv4/IPv6 sockets should be used. */ static boolean isIPv6Available() { - return false; - } - - static FileDescriptor serverSocket(boolean stream) throws IOException - { - return socket(stream); - } - - static FileDescriptor socket(boolean stream) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - FileDescriptor fd = new FileDescriptor(); - if (stream) - { - fd.setSocket(new cli.System.Net.Sockets.Socket(AddressFamily.wrap(AddressFamily.InterNetwork), SocketType.wrap(SocketType.Stream), ProtocolType.wrap(ProtocolType.Tcp))); - } - else - { - fd.setSocket(new cli.System.Net.Sockets.Socket(AddressFamily.wrap(AddressFamily.InterNetwork), SocketType.wrap(SocketType.Dgram), ProtocolType.wrap(ProtocolType.Udp))); - } - return fd; - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - } - - static void bind(FileDescriptor fd, InetAddress addr, int port) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - fd.getSocket().Bind(new IPEndPoint(SocketUtil.getAddressFromInetAddress(addr), port)); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - static void configureBlocking(FileDescriptor fd, boolean blocking) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - fd.getSocket().set_Blocking(blocking); - } - catch (cli.System.Net.Sockets.SocketException x) - { - if (x.get_ErrorCode() == SocketUtil.WSAEINVAL) - { - // Work around for winsock issue. You can't set a socket to blocking if a connection request is pending, - // so we'll have to set the blocking again in SocketChannelImpl.checkConnect(). - return; - } - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException _) - { - throw new SocketException("Socket is closed"); - } - } - - static InetSocketAddress localAddress(FileDescriptor fd) - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - IPEndPoint ep = (IPEndPoint)fd.getSocket().get_LocalEndPoint(); - return new InetSocketAddress(SocketUtil.getInetAddressFromIPEndPoint(ep), ep.get_Port()); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new Error(x); - } - catch (cli.System.ObjectDisposedException x) - { - throw new Error(x); - } - } - - static int localPortNumber(FileDescriptor fd) - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - IPEndPoint ep = (IPEndPoint)fd.getSocket().get_LocalEndPoint(); - return ep == null ? 0 : ep.get_Port(); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new Error(x); - } - catch (cli.System.ObjectDisposedException x) - { - throw new Error(x); - } - } - - private static int mapSocketOptionLevel(int opt) throws IOException - { - switch (opt) - { - case SocketOptions.SO_BROADCAST: - case SocketOptions.SO_KEEPALIVE: - case SocketOptions.SO_LINGER: - case SocketOptions.SO_OOBINLINE: - case SocketOptions.SO_RCVBUF: - case SocketOptions.SO_SNDBUF: - case SocketOptions.SO_REUSEADDR: - return SocketOptionLevel.Socket; - case SocketOptions.IP_MULTICAST_LOOP: - case SocketOptions.IP_TOS: - return SocketOptionLevel.IP; - case SocketOptions.TCP_NODELAY: - return SocketOptionLevel.Tcp; - default: - throw new SocketException("unsupported socket option: " + opt); - } - } - - private static int mapSocketOptionName(int opt) throws IOException - { - switch (opt) - { - case SocketOptions.SO_BROADCAST: - return SocketOptionName.Broadcast; - case SocketOptions.SO_KEEPALIVE: - return SocketOptionName.KeepAlive; - case SocketOptions.SO_LINGER: - return SocketOptionName.Linger; - case SocketOptions.SO_OOBINLINE: - return SocketOptionName.OutOfBandInline; - case SocketOptions.SO_RCVBUF: - return SocketOptionName.ReceiveBuffer; - case SocketOptions.SO_SNDBUF: - return SocketOptionName.SendBuffer; - case SocketOptions.SO_REUSEADDR: - return SocketOptionName.ReuseAddress; - case SocketOptions.IP_MULTICAST_LOOP: - return SocketOptionName.MulticastLoopback; - case SocketOptions.IP_TOS: - return SocketOptionName.TypeOfService; - case SocketOptions.TCP_NODELAY: - return SocketOptionName.NoDelay; - default: - throw new SocketException("unsupported socket option: " + opt); + if (!checkedIPv6) { + isIPv6Available = isIPv6Available0(); + checkedIPv6 = true; } + return isIPv6Available; } - static void setIntOption(FileDescriptor fd, int opt, int arg) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - int level = mapSocketOptionLevel(opt); - int name = mapSocketOptionName(opt); - fd.getSocket().SetSocketOption(SocketOptionLevel.wrap(level), SocketOptionName.wrap(name), arg); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - static int getIntOption(FileDescriptor fd, int opt) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - int level = mapSocketOptionLevel(opt); - int name = mapSocketOptionName(opt); - Object obj = fd.getSocket().GetSocketOption(SocketOptionLevel.wrap(level), SocketOptionName.wrap(name)); - if (obj instanceof LingerOption) - { - LingerOption lo = (LingerOption)obj; - return lo.get_Enabled() ? lo.get_LingerTime() : -1; - } - return CIL.unbox_int(obj); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private static int readImpl(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException - { - if (length == 0) - { - return 0; - } - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - int read = fd.getSocket().Receive(buf, offset, length, SocketFlags.wrap(SocketFlags.None)); - return read == 0 ? IOStatus.EOF : read; - } - catch (cli.System.Net.Sockets.SocketException x) - { - if (x.get_ErrorCode() == SocketUtil.WSAESHUTDOWN) - { - // the socket was shutdown, so we have to return EOF - return IOStatus.EOF; - } - else if (x.get_ErrorCode() == SocketUtil.WSAEWOULDBLOCK) - { - // nothing to read and would block - return IOStatus.UNAVAILABLE; - } - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - static int read(FileDescriptor fd, ByteBuffer dst) throws IOException - { - if (dst.hasArray()) - { - byte[] buf = dst.array(); - int len = readImpl(fd, buf, dst.arrayOffset() + dst.position(), dst.remaining()); - if (len > 0) - { - dst.position(dst.position() + len); - } - return len; - } - else - { - byte[] buf = new byte[dst.remaining()]; - int len = readImpl(fd, buf, 0, buf.length); - if (len > 0) - { - dst.put(buf, 0, len); - } - return len; - } - } - - static long read(FileDescriptor fd, ByteBuffer[] dsts) throws IOException - { - long totalRead = 0; - for (int i = 0; i < dsts.length; i++) - { - int size = dsts[i].remaining(); - if (size > 0) - { - int read = read(fd, dsts[i]); - if (read < 0) - { - break; - } - totalRead += read; - if (read < size || safeGetAvailable(fd) == 0) - { - break; - } - } - } - return totalRead; - } - - private static int safeGetAvailable(FileDescriptor fd) - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - return fd.getSocket().get_Available(); - } - catch (cli.System.Net.Sockets.SocketException x) - { - } - catch (cli.System.ObjectDisposedException x1) - { - } - return 0; - } - - private static int writeImpl(FileDescriptor fd, byte[] buf, int offset, int length) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - return fd.getSocket().Send(buf, offset, length, SocketFlags.wrap(SocketFlags.None)); - } - catch (cli.System.Net.Sockets.SocketException x) - { - if (x.get_ErrorCode() == SocketUtil.WSAEWOULDBLOCK) - { - return IOStatus.UNAVAILABLE; - } - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - static int write(FileDescriptor fd, ByteBuffer src) throws IOException - { - if (src.hasArray()) - { - byte[] buf = src.array(); - int len = writeImpl(fd, buf, src.arrayOffset() + src.position(), src.remaining()); - if (len > 0) - { - src.position(src.position() + len); - } - return len; - } - else - { - int pos = src.position(); - byte[] buf = new byte[src.remaining()]; - src.get(buf); - int len = writeImpl(fd, buf, 0, buf.length); - if (len > 0) - { - src.position(pos + len); - } - return len; - } + /** + * Tells whether IPv6 sockets can join IPv4 multicast groups + */ + static boolean canIPv6SocketJoinIPv4Group() { + return canIPv6SocketJoinIPv4Group0(); } - static long write(FileDescriptor fd, ByteBuffer[] srcs) throws IOException - { - long totalWritten = 0; - for (int i = 0; i < srcs.length; i++) - { - int size = srcs[i].remaining(); - if (size > 0) - { - int written = write(fd, srcs[i]); - if (written < 0) - { - break; - } - totalWritten += written; - if (written < size) - { - break; - } - } - } - return totalWritten; + /** + * Tells whether {@link #join6} can be used to join an IPv4 + * multicast group (IPv4 group as IPv4-mapped IPv6 address) + */ + static boolean canJoin6WithIPv4Group() { + return canJoin6WithIPv4Group0(); } - // -- Miscellaneous utilities -- - static InetSocketAddress checkAddress(SocketAddress sa) { if (sa == null) - throw new IllegalArgumentException(); + throw new NullPointerException(); if (!(sa instanceof InetSocketAddress)) throw new UnsupportedAddressTypeException(); // ## needs arg InetSocketAddress isa = (InetSocketAddress)sa; @@ -468,6 +103,8 @@ class Net { // package-private Exception nx = x; if (x instanceof ClosedChannelException) nx = new SocketException("Socket is closed"); + else if (x instanceof NotYetConnectedException) + nx = new SocketException("Socket is not connected"); else if (x instanceof AlreadyBoundException) nx = new SocketException("Already bound"); else if (x instanceof NotYetBoundException) @@ -587,10 +224,9 @@ class Net { // package-private // -- Socket options - static void setSocketOption(FileDescriptor fd, ProtocolFamily family, - SocketOption<?> name, Object value) - throws IOException + SocketOption<?> name, Object value) + throws IOException { if (value == null) throw new IllegalArgumentException("Invalid option value"); @@ -644,9 +280,9 @@ class Net { // package-private } static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, - SocketOption<?> name) - throws IOException - { + SocketOption<?> name) + throws IOException + { Class<?> type = name.type(); // only simple values supported by this method @@ -666,48 +302,207 @@ class Net { // package-private } else { return (value == 0) ? Boolean.FALSE : Boolean.TRUE; } - } + } + + // -- Socket operations -- + + private static native boolean isIPv6Available0(); + + private static native boolean canIPv6SocketJoinIPv4Group0(); + + private static native boolean canJoin6WithIPv4Group0(); + + static FileDescriptor socket(boolean stream) throws IOException { + return socket(UNSPEC, stream); + } + + static FileDescriptor socket(ProtocolFamily family, boolean stream) + throws IOException { + boolean preferIPv6 = isIPv6Available() && + (family != StandardProtocolFamily.INET); + return socket0(preferIPv6, stream, false); + } + + static FileDescriptor serverSocket(boolean stream) { + return socket0(isIPv6Available(), stream, true); + } + + // Due to oddities SO_REUSEADDR on windows reuse is ignored + private static native FileDescriptor socket0(boolean preferIPv6, boolean stream, boolean reuse); + + static void bind(FileDescriptor fd, InetAddress addr, int port) + throws IOException + { + bind(UNSPEC, fd, addr, port); + } + + static void bind(ProtocolFamily family, FileDescriptor fd, + InetAddress addr, int port) throws IOException + { + boolean preferIPv6 = isIPv6Available() && + (family != StandardProtocolFamily.INET); + bind0(preferIPv6, fd, addr, port); + } + + private static native void bind0(boolean preferIPv6, FileDescriptor fd, + InetAddress addr, int port) + throws IOException; + + static native void listen(FileDescriptor fd, int backlog) throws IOException; + + static int connect(FileDescriptor fd, InetAddress remote, int remotePort) + throws IOException + { + return connect(UNSPEC, fd, remote, remotePort); + } + + static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort) + throws IOException + { + boolean preferIPv6 = isIPv6Available() && + (family != StandardProtocolFamily.INET); + return connect0(preferIPv6, fd, remote, remotePort); + } + + private static native int connect0(boolean preferIPv6, + FileDescriptor fd, + InetAddress remote, + int remotePort) + throws IOException; + - public final static int SHUT_RD = 0; public final static int SHUT_WR = 1; public final static int SHUT_RDWR = 2; - static /*native*/ void shutdown(FileDescriptor fd, int how) throws IOException + static native void shutdown(FileDescriptor fd, int how) throws IOException; + + private static native int localPort(FileDescriptor fd) + throws IOException; + + private static native InetAddress localInetAddress(FileDescriptor fd) + throws IOException; + + static InetSocketAddress localAddress(FileDescriptor fd) + throws IOException { - throw new NotYetImplementedError(); //TODO JDK7 + return new InetSocketAddress(localInetAddress(fd), localPort(fd)); } - private static /*native*/ int getIntOption0(FileDescriptor fd, boolean mayNeedConversion, - int level, int opt) - throws IOException - { - throw new NotYetImplementedError(); //TODO JDK7 - } + private static native int remotePort(FileDescriptor fd) + throws IOException; + + private static native InetAddress remoteInetAddress(FileDescriptor fd) + throws IOException; - private static /*native*/ void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, - int level, int opt, int arg) + static InetSocketAddress remoteAddress(FileDescriptor fd) + throws IOException { - throw new NotYetImplementedError(); //TODO JDK7 + return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd)); } - static /*native*/ void setInterface4(FileDescriptor fd, int interf) throws IOException + private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion, + int level, int opt) + throws IOException; + + private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, + int level, int opt, int arg) + throws IOException; + + // -- Multicast support -- + + + /** + * Join IPv4 multicast group + */ + static int join4(FileDescriptor fd, int group, int interf, int source) + throws IOException { - throw new NotYetImplementedError(); //TODO JDK7 + return joinOrDrop4(true, fd, group, interf, source); } - - static /*native*/ int getInterface4(FileDescriptor fd) throws IOException + + /** + * Drop membership of IPv4 multicast group + */ + static void drop4(FileDescriptor fd, int group, int interf, int source) + throws IOException { - throw new NotYetImplementedError(); //TODO JDK7 + joinOrDrop4(false, fd, group, interf, source); } - - static /*native*/ void setInterface6(FileDescriptor fd, int index) throws IOException + + private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source) + throws IOException; + + /** + * Block IPv4 source + */ + static int block4(FileDescriptor fd, int group, int interf, int source) + throws IOException { - throw new NotYetImplementedError(); //TODO JDK7 + return blockOrUnblock4(true, fd, group, interf, source); } - - static /*native*/ int getInterface6(FileDescriptor fd) throws IOException + + /** + * Unblock IPv6 source + */ + static void unblock4(FileDescriptor fd, int group, int interf, int source) + throws IOException { - throw new NotYetImplementedError(); //TODO JDK7 + blockOrUnblock4(false, fd, group, interf, source); } + + private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group, + int interf, int source) + throws IOException; + + /** + * Join IPv6 multicast group + */ + static int join6(FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException + { + return joinOrDrop6(true, fd, group, index, source); + } + + /** + * Drop membership of IPv6 multicast group + */ + static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException + { + joinOrDrop6(false, fd, group, index, source); + } + + private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException; + + /** + * Block IPv6 source + */ + static int block6(FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException + { + return blockOrUnblock6(true, fd, group, index, source); + } + + /** + * Unblock IPv6 source + */ + static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException + { + blockOrUnblock6(false, fd, group, index, source); + } + + static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source) + throws IOException; + + static native void setInterface4(FileDescriptor fd, int interf) throws IOException; + + static native int getInterface4(FileDescriptor fd) throws IOException; + + static native void setInterface6(FileDescriptor fd, int index) throws IOException; + + static native int getInterface6(FileDescriptor fd) throws IOException; + } diff --git a/openjdk/sun/nio/ch/ServerSocketChannelImpl.java b/openjdk/sun/nio/ch/ServerSocketChannelImpl.java deleted file mode 100644 index 9778dcaa..00000000 --- a/openjdk/sun/nio/ch/ServerSocketChannelImpl.java +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.nio.ch; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.lang.reflect.*; -import java.net.*; -import java.nio.channels.*; -import java.nio.channels.spi.*; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - - -/** - * An implementation of ServerSocketChannels - */ - -class ServerSocketChannelImpl - extends ServerSocketChannel - implements SelChImpl -{ - // Our file descriptor - private final FileDescriptor fd; - - // ID of native thread currently blocked in this channel, for signalling - private volatile long thread = 0; - - // Lock held by thread currently blocked in this channel - private final Object lock = new Object(); - - // Lock held by any thread that modifies the state fields declared below - // DO NOT invoke a blocking I/O operation while holding this lock! - private final Object stateLock = new Object(); - - // -- The following fields are protected by stateLock - - // Channel state, increases monotonically - private static final int ST_UNINITIALIZED = -1; - private static final int ST_INUSE = 0; - private static final int ST_KILLED = 1; - private int state = ST_UNINITIALIZED; - - // Binding - private SocketAddress localAddress = null; // null => unbound - - // Options, created on demand - private SocketOpts.IP.TCP options = null; - - // Our socket adaptor, if any - ServerSocket socket; - - // -- End of fields protected by stateLock - - - public ServerSocketChannelImpl(SelectorProvider sp) throws IOException { - super(sp); - this.fd = Net.serverSocket(true); - this.state = ST_INUSE; - } - - public ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd) - throws IOException - { - super(sp); - this.fd = fd; - this.state = ST_INUSE; - localAddress = Net.localAddress(fd); - } - - public ServerSocket socket() { - synchronized (stateLock) { - if (socket == null) - socket = ServerSocketAdaptor.create(this); - return socket; - } - } - - public SocketAddress getLocalAddress() throws IOException { - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - return localAddress; - } - } - - public <T> ServerSocketChannel setOption(SocketOption<T> name, T value) throws IOException - { - if (name == null) - throw new NullPointerException(); - if (!supportedOptions().contains(name)) - throw new UnsupportedOperationException("'" + name + "' not supported"); - - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - - // no options that require special handling - Net.setSocketOption(fd, Net.UNSPEC, name, value); - return this; - } - } - - @SuppressWarnings("unchecked") - public <T> T getOption(SocketOption<T> name) throws IOException - { - if (name == null) - throw new NullPointerException(); - if (!supportedOptions().contains(name)) - throw new UnsupportedOperationException("'" + name + "' not supported"); - - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - - // no options that require special handling - return (T) Net.getSocketOption(fd, Net.UNSPEC, name); - } - } - - private static class DefaultOptionsHolder { - static final Set<SocketOption<?>> defaultOptions = defaultOptions(); - - private static Set<SocketOption<?>> defaultOptions() { - HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2); - set.add(StandardSocketOptions.SO_RCVBUF); - set.add(StandardSocketOptions.SO_REUSEADDR); - return Collections.unmodifiableSet(set); - } - } - - public final Set<SocketOption<?>> supportedOptions() { - return DefaultOptionsHolder.defaultOptions; - } - - public boolean isBound() { - synchronized (stateLock) { - return localAddress != null; - } - } - - public SocketAddress localAddress() { - synchronized (stateLock) { - return localAddress; - } - } - - public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException { - synchronized (lock) { - if (!isOpen()) - throw new ClosedChannelException(); - if (isBound()) - throw new AlreadyBoundException(); - InetSocketAddress isa = Net.checkAddress(local); - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkListen(isa.getPort()); - Net.bind(fd, isa.getAddress(), isa.getPort()); - listen(fd, backlog < 1 ? 50 : backlog); - synchronized (stateLock) { - localAddress = Net.localAddress(fd); - } - } - return this; - } - - public SocketChannel accept() throws IOException { - synchronized (lock) { - if (!isOpen()) - throw new ClosedChannelException(); - if (!isBound()) - throw new NotYetBoundException(); - SocketChannel sc = null; - - int n = 0; - FileDescriptor newfd = new FileDescriptor(); - InetSocketAddress[] isaa = new InetSocketAddress[1]; - - try { - begin(); - if (!isOpen()) - return null; - thread = NativeThread.current(); - for (;;) { - n = accept0(this.fd, newfd, isaa); - if ((n == IOStatus.INTERRUPTED) && isOpen()) - continue; - break; - } - } finally { - thread = 0; - end(n > 0); - assert IOStatus.check(n); - } - - if (n < 1) - return null; - - IOUtil.configureBlocking(newfd, true); - InetSocketAddress isa = isaa[0]; - sc = new SocketChannelImpl(provider(), newfd, isa); - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkAccept(isa.getAddress().getHostAddress(), - isa.getPort()); - } catch (SecurityException x) { - sc.close(); - throw x; - } - } - return sc; - - } - } - - protected void implConfigureBlocking(boolean block) throws IOException { - IOUtil.configureBlocking(fd, block); - } - - public SocketOpts options() { - synchronized (stateLock) { - if (options == null) { - SocketOptsImpl.Dispatcher d - = new SocketOptsImpl.Dispatcher() { - int getInt(int opt) throws IOException { - return Net.getIntOption(fd, opt); - } - void setInt(int opt, int arg) throws IOException { - Net.setIntOption(fd, opt, arg); - } - }; - options = new SocketOptsImpl.IP.TCP(d); - } - return options; - } - } - - protected void implCloseSelectableChannel() throws IOException { - synchronized (stateLock) { - closeImpl(); - long th = thread; - if (th != 0) - NativeThread.signal(th); - if (!isRegistered()) - kill(); - } - } - - public void kill() throws IOException { - synchronized (stateLock) { - if (state == ST_KILLED) - return; - if (state == ST_UNINITIALIZED) { - state = ST_KILLED; - return; - } - assert !isOpen() && !isRegistered(); - closeImpl(); - state = ST_KILLED; - } - } - - /** - * Translates native poll revent set into a ready operation set - */ - public boolean translateReadyOps(int ops, int initialOps, - SelectionKeyImpl sk) { - int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes - int oldOps = sk.nioReadyOps(); - int newOps = initialOps; - - if ((ops & PollArrayWrapper.POLLNVAL) != 0) { - // This should only happen if this channel is pre-closed while a - // selection operation is in progress - // ## Throw an error if this channel has not been pre-closed - return false; - } - - if ((ops & (PollArrayWrapper.POLLERR - | PollArrayWrapper.POLLHUP)) != 0) { - newOps = intOps; - sk.nioReadyOps(newOps); - return (newOps & ~oldOps) != 0; - } - - if (((ops & PollArrayWrapper.POLLIN) != 0) && - ((intOps & SelectionKey.OP_ACCEPT) != 0)) - newOps |= SelectionKey.OP_ACCEPT; - - sk.nioReadyOps(newOps); - return (newOps & ~oldOps) != 0; - } - - public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) { - return translateReadyOps(ops, sk.nioReadyOps(), sk); - } - - public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) { - return translateReadyOps(ops, 0, sk); - } - - /** - * Translates an interest operation set into a native poll event set - */ - public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) { - int newOps = 0; - - // Translate ops - if ((ops & SelectionKey.OP_ACCEPT) != 0) - newOps |= PollArrayWrapper.POLLIN; - // Place ops into pollfd array - sk.selector.putEventOps(sk, newOps); - } - - public FileDescriptor getFD() { - return fd; - } - - public int getFDVal() { - throw new Error(); - } - - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append(this.getClass().getName()); - sb.append('['); - if (!isOpen()) - sb.append("closed"); - else { - synchronized (stateLock) { - if (localAddress() == null) { - sb.append("unbound"); - } else { - sb.append(localAddress().toString()); - } - } - } - sb.append(']'); - return sb.toString(); - } - - // -- Native methods -- - - private static void listen(FileDescriptor fd, int backlog) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - fd.getSocket().Listen(backlog); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException _) - { - throw new SocketException("Socket is closed"); - } - } - - // Accepts a new connection, setting the given file descriptor to refer to - // the new socket and setting isaa[0] to the socket's remote address. - // Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no - // connections are pending) or IOStatus.INTERRUPTED. - // - private static int accept0(FileDescriptor ssfd, FileDescriptor newfd, InetSocketAddress[] isaa) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - cli.System.Net.Sockets.Socket netSocket = ssfd.getSocket(); - if (netSocket.get_Blocking() || netSocket.Poll(0, cli.System.Net.Sockets.SelectMode.wrap(cli.System.Net.Sockets.SelectMode.SelectRead))) - { - cli.System.Net.Sockets.Socket accsock = netSocket.Accept(); - newfd.setSocket(accsock); - cli.System.Net.IPEndPoint ep = (cli.System.Net.IPEndPoint)accsock.get_RemoteEndPoint(); - isaa[0] = new InetSocketAddress(SocketUtil.getInetAddressFromIPEndPoint(ep), ep.get_Port()); - return 1; - } - else - { - return IOStatus.UNAVAILABLE; - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException _) - { - throw new SocketException("Socket is closed"); - } - } - - private void closeImpl() throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - fd.getSocket().Close(); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - -} diff --git a/openjdk/sun/nio/ch/SocketChannelImpl.java b/openjdk/sun/nio/ch/SocketChannelImpl.java deleted file mode 100644 index cb576b46..00000000 --- a/openjdk/sun/nio/ch/SocketChannelImpl.java +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.nio.ch; - -import ikvm.internal.NotYetImplementedError; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.net.*; -import java.nio.ByteBuffer; -import java.nio.channels.*; -import java.nio.channels.spi.*; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - - -/** - * An implementation of SocketChannels - */ - -class SocketChannelImpl - extends SocketChannel - implements SelChImpl -{ - // Our file descriptor object - private final FileDescriptor fd; - private volatile cli.System.IAsyncResult asyncConnect; - - // IDs of native threads doing reads and writes, for signalling - private volatile long readerThread = 0; - private volatile long writerThread = 0; - - // Lock held by current reading or connecting thread - private final Object readLock = new Object(); - - // Lock held by current writing or connecting thread - private final Object writeLock = new Object(); - - // Lock held by any thread that modifies the state fields declared below - // DO NOT invoke a blocking I/O operation while holding this lock! - private final Object stateLock = new Object(); - - // -- The following fields are protected by stateLock - - // State, increases monotonically - private static final int ST_UNINITIALIZED = -1; - private static final int ST_UNCONNECTED = 0; - private static final int ST_PENDING = 1; - private static final int ST_CONNECTED = 2; - private static final int ST_KILLPENDING = 3; - private static final int ST_KILLED = 4; - private int state = ST_UNINITIALIZED; - - // Binding - private SocketAddress localAddress = null; - private SocketAddress remoteAddress = null; - - // Input/Output open - private boolean isInputOpen = true; - private boolean isOutputOpen = true; - private boolean readyToConnect = false; - - // Options, created on demand - private SocketOpts.IP.TCP options = null; - - // Socket adaptor, created on demand - private Socket socket = null; - - // -- End of fields protected by stateLock - - - // Constructor for normal connecting sockets - // - SocketChannelImpl(SelectorProvider sp) throws IOException { - super(sp); - this.fd = Net.socket(true); - this.state = ST_UNCONNECTED; - } - - // Constructor for sockets obtained from server sockets - // - SocketChannelImpl(SelectorProvider sp, - FileDescriptor fd, InetSocketAddress remote) - throws IOException - { - super(sp); - this.fd = fd; - this.state = ST_CONNECTED; - this.remoteAddress = remote; - } - - public Socket socket() { - synchronized (stateLock) { - if (socket == null) - socket = SocketAdaptor.create(this); - return socket; - } - } - - public SocketAddress getLocalAddress() throws IOException { - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - return localAddress; - } - } - - public SocketAddress getRemoteAddress() throws IOException { - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - return remoteAddress; - } - } - - public <T> SocketChannel setOption(SocketOption<T> name, T value) - throws IOException - { - if (name == null) - throw new NullPointerException(); - if (!supportedOptions().contains(name)) - throw new UnsupportedOperationException("'" + name + "' not supported"); - - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - - // special handling for IP_TOS: no-op when IPv6 - if (name == StandardSocketOptions.IP_TOS) { - if (!Net.isIPv6Available()) - Net.setSocketOption(fd, StandardProtocolFamily.INET, name, value); - return this; - } - - // no options that require special handling - Net.setSocketOption(fd, Net.UNSPEC, name, value); - return this; - } - } - - @SuppressWarnings("unchecked") - public <T> T getOption(SocketOption<T> name) - throws IOException - { - if (name == null) - throw new NullPointerException(); - if (!supportedOptions().contains(name)) - throw new UnsupportedOperationException("'" + name + "' not supported"); - - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - - // special handling for IP_TOS: always return 0 when IPv6 - if (name == StandardSocketOptions.IP_TOS) { - return (Net.isIPv6Available()) ? (T) Integer.valueOf(0) : - (T) Net.getSocketOption(fd, StandardProtocolFamily.INET, name); - } - - // no options that require special handling - return (T) Net.getSocketOption(fd, Net.UNSPEC, name); - } - } - - private static class DefaultOptionsHolder { - static final Set<SocketOption<?>> defaultOptions = defaultOptions(); - - private static Set<SocketOption<?>> defaultOptions() { - HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8); - set.add(StandardSocketOptions.SO_SNDBUF); - set.add(StandardSocketOptions.SO_RCVBUF); - set.add(StandardSocketOptions.SO_KEEPALIVE); - set.add(StandardSocketOptions.SO_REUSEADDR); - set.add(StandardSocketOptions.SO_LINGER); - set.add(StandardSocketOptions.TCP_NODELAY); - // additional options required by socket adaptor - set.add(StandardSocketOptions.IP_TOS); - set.add(ExtendedSocketOption.SO_OOBINLINE); - return Collections.unmodifiableSet(set); - } - } - - public final Set<SocketOption<?>> supportedOptions() { - return DefaultOptionsHolder.defaultOptions; - } - - private boolean ensureReadOpen() throws ClosedChannelException { - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - if (!isConnected()) - throw new NotYetConnectedException(); - if (!isInputOpen) - return false; - else - return true; - } - } - - private void ensureWriteOpen() throws ClosedChannelException { - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - if (!isOutputOpen) - throw new ClosedChannelException(); - if (!isConnected()) - throw new NotYetConnectedException(); - } - } - - private void readerCleanup() throws IOException { - synchronized (stateLock) { - readerThread = 0; - if (state == ST_KILLPENDING) - kill(); - } - } - - private void writerCleanup() throws IOException { - synchronized (stateLock) { - writerThread = 0; - if (state == ST_KILLPENDING) - kill(); - } - } - - public int read(ByteBuffer buf) throws IOException { - - if (buf == null) - throw new NullPointerException(); - - synchronized (readLock) { - if (!ensureReadOpen()) - return -1; - int n = 0; - try { - - // Set up the interruption machinery; see - // AbstractInterruptibleChannel for details - // - begin(); - - synchronized (stateLock) { - if (!isOpen()) { - // Either the current thread is already interrupted, so - // begin() closed the channel, or another thread closed the - // channel since we checked it a few bytecodes ago. In - // either case the value returned here is irrelevant since - // the invocation of end() in the finally block will throw - // an appropriate exception. - // - return 0; - - } - - // Save this thread so that it can be signalled on those - // platforms that require it - // - readerThread = NativeThread.current(); - } - - // Between the previous test of isOpen() and the return of the - // IOUtil.read invocation below, this channel might be closed - // or this thread might be interrupted. We rely upon the - // implicit synchronization point in the kernel read() call to - // make sure that the right thing happens. In either case the - // implCloseSelectableChannel method is ultimately invoked in - // some other thread, so there are three possibilities: - // - // - implCloseSelectableChannel() invokes nd.preClose() - // before this thread invokes read(), in which case the - // read returns immediately with either EOF or an error, - // the latter of which will cause an IOException to be - // thrown. - // - // - implCloseSelectableChannel() invokes nd.preClose() after - // this thread is blocked in read(). On some operating - // systems (e.g., Solaris and Windows) this causes the read - // to return immediately with either EOF or an error - // indication. - // - // - implCloseSelectableChannel() invokes nd.preClose() after - // this thread is blocked in read() but the operating - // system (e.g., Linux) doesn't support preemptive close, - // so implCloseSelectableChannel() proceeds to signal this - // thread, thereby causing the read to return immediately - // with IOStatus.INTERRUPTED. - // - // In all three cases the invocation of end() in the finally - // clause will notice that the channel has been closed and - // throw an appropriate exception (AsynchronousCloseException - // or ClosedByInterruptException) if necessary. - // - // *There is A fourth possibility. implCloseSelectableChannel() - // invokes nd.preClose(), signals reader/writer thred and quickly - // moves on to nd.close() in kill(), which does a real close. - // Then a third thread accepts a new connection, opens file or - // whatever that causes the released "fd" to be recycled. All - // above happens just between our last isOpen() check and the - // next kernel read reached, with the recycled "fd". The solution - // is to postpone the real kill() if there is a reader or/and - // writer thread(s) over there "waiting", leave the cleanup/kill - // to the reader or writer thread. (the preClose() still happens - // so the connection gets cut off as usual). - // - // For socket channels there is the additional wrinkle that - // asynchronous shutdown works much like asynchronous close, - // except that the channel is shutdown rather than completely - // closed. This is analogous to the first two cases above, - // except that the shutdown operation plays the role of - // nd.preClose(). - for (;;) { - n = Net.read(fd, buf); - if ((n == IOStatus.INTERRUPTED) && isOpen()) { - // The system call was interrupted but the channel - // is still open, so retry - continue; - } - return IOStatus.normalize(n); - } - - } finally { - readerCleanup(); // Clear reader thread - // The end method, which is defined in our superclass - // AbstractInterruptibleChannel, resets the interruption - // machinery. If its argument is true then it returns - // normally; otherwise it checks the interrupt and open state - // of this channel and throws an appropriate exception if - // necessary. - // - // So, if we actually managed to do any I/O in the above try - // block then we pass true to the end method. We also pass - // true if the channel was in non-blocking mode when the I/O - // operation was initiated but no data could be transferred; - // this prevents spurious exceptions from being thrown in the - // rare event that a channel is closed or a thread is - // interrupted at the exact moment that a non-blocking I/O - // request is made. - // - end(n > 0 || (n == IOStatus.UNAVAILABLE)); - - // Extra case for socket channels: Asynchronous shutdown - // - synchronized (stateLock) { - if ((n <= 0) && (!isInputOpen)) - return IOStatus.EOF; - } - - assert IOStatus.check(n); - - } - } - } - - private long read0(ByteBuffer[] bufs) throws IOException { - if (bufs == null) - throw new NullPointerException(); - synchronized (readLock) { - if (!ensureReadOpen()) - return -1; - long n = 0; - try { - begin(); - synchronized (stateLock) { - if (!isOpen()) - return 0; - readerThread = NativeThread.current(); - } - - for (;;) { - n = Net.read(fd, bufs); - if ((n == IOStatus.INTERRUPTED) && isOpen()) - continue; - return IOStatus.normalize(n); - } - } finally { - readerCleanup(); - end(n > 0 || (n == IOStatus.UNAVAILABLE)); - synchronized (stateLock) { - if ((n <= 0) && (!isInputOpen)) - return IOStatus.EOF; - } - assert IOStatus.check(n); - } - } - } - - public long read(ByteBuffer[] dsts, int offset, int length) - throws IOException - { - if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) - throw new IndexOutOfBoundsException(); - // ## Fix IOUtil.write so that we can avoid this array copy - return read0(Util.subsequence(dsts, offset, length)); - } - - public int write(ByteBuffer buf) throws IOException { - if (buf == null) - throw new NullPointerException(); - synchronized (writeLock) { - ensureWriteOpen(); - int n = 0; - try { - begin(); - synchronized (stateLock) { - if (!isOpen()) - return 0; - writerThread = NativeThread.current(); - } - for (;;) { - n = Net.write(fd, buf); - if ((n == IOStatus.INTERRUPTED) && isOpen()) - continue; - return IOStatus.normalize(n); - } - } finally { - writerCleanup(); - end(n > 0 || (n == IOStatus.UNAVAILABLE)); - synchronized (stateLock) { - if ((n <= 0) && (!isOutputOpen)) - throw new AsynchronousCloseException(); - } - assert IOStatus.check(n); - } - } - } - - public long write0(ByteBuffer[] bufs) throws IOException { - if (bufs == null) - throw new NullPointerException(); - synchronized (writeLock) { - ensureWriteOpen(); - long n = 0; - try { - begin(); - synchronized (stateLock) { - if (!isOpen()) - return 0; - writerThread = NativeThread.current(); - } - for (;;) { - n = Net.write(fd, bufs); - if ((n == IOStatus.INTERRUPTED) && isOpen()) - continue; - return IOStatus.normalize(n); - } - } finally { - writerCleanup(); - end((n > 0) || (n == IOStatus.UNAVAILABLE)); - synchronized (stateLock) { - if ((n <= 0) && (!isOutputOpen)) - throw new AsynchronousCloseException(); - } - assert IOStatus.check(n); - } - } - } - - public long write(ByteBuffer[] srcs, int offset, int length) - throws IOException - { - if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) - throw new IndexOutOfBoundsException(); - // ## Fix IOUtil.write so that we can avoid this array copy - return write0(Util.subsequence(srcs, offset, length)); - } - - protected void implConfigureBlocking(boolean block) throws IOException { - IOUtil.configureBlocking(fd, block); - } - - public SocketOpts options() { - synchronized (stateLock) { - if (options == null) { - SocketOptsImpl.Dispatcher d - = new SocketOptsImpl.Dispatcher() { - int getInt(int opt) throws IOException { - return Net.getIntOption(fd, opt); - } - void setInt(int opt, int arg) - throws IOException - { - Net.setIntOption(fd, opt, arg); - } - }; - options = new SocketOptsImpl.IP.TCP(d); - } - return options; - } - } - - // package-private - int sendOutOfBandData(byte b) throws IOException { - synchronized (writeLock) { - ensureWriteOpen(); - int n = 0; - try { - begin(); - synchronized (stateLock) { - if (!isOpen()) - return 0; - writerThread = NativeThread.current(); - } - for (;;) { - n = sendOutOfBandData(fd, b); - if ((n == IOStatus.INTERRUPTED) && isOpen()) - continue; - return IOStatus.normalize(n); - } - } finally { - writerCleanup(); - end((n > 0) || (n == IOStatus.UNAVAILABLE)); - synchronized (stateLock) { - if ((n <= 0) && (!isOutputOpen)) - throw new AsynchronousCloseException(); - } - assert IOStatus.check(n); - } - } - } - - public boolean isBound() { - synchronized (stateLock) { - if (state == ST_CONNECTED) - return true; - return localAddress != null; - } - } - - public SocketAddress localAddress() { - synchronized (stateLock) { - if (state == ST_CONNECTED && - (localAddress == null || - ((InetSocketAddress)localAddress).getAddress().isAnyLocalAddress())) { - // Socket was not bound before connecting or - // Socket was bound with an "anyLocalAddress" - localAddress = Net.localAddress(fd); - } - return localAddress; - } - } - - public SocketAddress remoteAddress() { - synchronized (stateLock) { - return remoteAddress; - } - } - - public SocketChannel bind(SocketAddress local) throws IOException { - synchronized (readLock) { - synchronized (writeLock) { - synchronized (stateLock) { - ensureOpenAndUnconnected(); - if (localAddress != null) - throw new AlreadyBoundException(); - InetSocketAddress isa = Net.checkAddress(local); - Net.bind(fd, isa.getAddress(), isa.getPort()); - localAddress = Net.localAddress(fd); - } - } - } - return this; - } - - public boolean isConnected() { - synchronized (stateLock) { - return (state == ST_CONNECTED); - } - } - - public boolean isConnectionPending() { - synchronized (stateLock) { - return (state == ST_PENDING); - } - } - - void ensureOpenAndUnconnected() throws IOException { // package-private - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - if (state == ST_CONNECTED) - throw new AlreadyConnectedException(); - if (state == ST_PENDING) - throw new ConnectionPendingException(); - } - } - - public boolean connect(SocketAddress sa) throws IOException { - int trafficClass = 0; // ## Pick up from options - int localPort = 0; - - synchronized (readLock) { - synchronized (writeLock) { - ensureOpenAndUnconnected(); - InetSocketAddress isa = Net.checkAddress(sa); - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkConnect(isa.getAddress().getHostAddress(), - isa.getPort()); - synchronized (blockingLock()) { - int n = 0; - try { - try { - begin(); - synchronized (stateLock) { - if (!isOpen()) { - return false; - } - readerThread = NativeThread.current(); - } - for (;;) { - InetAddress ia = isa.getAddress(); - if (ia.isAnyLocalAddress()) - ia = InetAddress.getLocalHost(); - n = connectImpl(ia, - isa.getPort(), - trafficClass); - if ( (n == IOStatus.INTERRUPTED) - && isOpen()) - continue; - break; - } - } finally { - readerCleanup(); - end((n > 0) || (n == IOStatus.UNAVAILABLE)); - assert IOStatus.check(n); - } - } catch (IOException x) { - // If an exception was thrown, close the channel after - // invoking end() so as to avoid bogus - // AsynchronousCloseExceptions - close(); - throw x; - } - synchronized (stateLock) { - remoteAddress = isa; - if (n > 0) { - - // Connection succeeded; disallow further - // invocation - state = ST_CONNECTED; - return true; - } - // If nonblocking and no exception then connection - // pending; disallow another invocation - if (!isBlocking()) - state = ST_PENDING; - else - assert false; - } - } - return false; - } - } - } - - public boolean finishConnect() throws IOException { - synchronized (readLock) { - synchronized (writeLock) { - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - if (state == ST_CONNECTED) - return true; - if (state != ST_PENDING) - throw new NoConnectionPendingException(); - } - int n = 0; - try { - try { - begin(); - synchronized (blockingLock()) { - synchronized (stateLock) { - if (!isOpen()) { - return false; - } - readerThread = NativeThread.current(); - } - if (!isBlocking()) { - for (;;) { - n = checkConnect(fd, false, - readyToConnect); - if ( (n == IOStatus.INTERRUPTED) - && isOpen()) - continue; - break; - } - } else { - for (;;) { - n = checkConnect(fd, true, - readyToConnect); - if (n == 0) { - // Loop in case of - // spurious notifications - continue; - } - if ( (n == IOStatus.INTERRUPTED) - && isOpen()) - continue; - break; - } - } - } - } finally { - synchronized (stateLock) { - readerThread = 0; - if (state == ST_KILLPENDING) { - kill(); - // poll()/getsockopt() does not report - // error (throws exception, with n = 0) - // on Linux platform after dup2 and - // signal-wakeup. Force n to 0 so the - // end() can throw appropriate exception - n = 0; - } - } - end((n > 0) || (n == IOStatus.UNAVAILABLE)); - assert IOStatus.check(n); - } - } catch (IOException x) { - // If an exception was thrown, close the channel after - // invoking end() so as to avoid bogus - // AsynchronousCloseExceptions - close(); - throw x; - } - if (n > 0) { - synchronized (stateLock) { - state = ST_CONNECTED; - } - return true; - } - return false; - } - } - } - - public final static int SHUT_RD = 0; - public final static int SHUT_WR = 1; - public final static int SHUT_RDWR = 2; - - public SocketChannel shutdownInput() throws IOException { - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - isInputOpen = false; - shutdown(fd, SHUT_RD); - if (readerThread != 0) - NativeThread.signal(readerThread); - return this; - } - } - - public SocketChannel shutdownOutput() throws IOException { - synchronized (stateLock) { - if (!isOpen()) - throw new ClosedChannelException(); - isOutputOpen = false; - shutdown(fd, SHUT_WR); - if (writerThread != 0) - NativeThread.signal(writerThread); - return this; - } - } - - public boolean isInputOpen() { - synchronized (stateLock) { - return isInputOpen; - } - } - - public boolean isOutputOpen() { - synchronized (stateLock) { - return isOutputOpen; - } - } - - // AbstractInterruptibleChannel synchronizes invocations of this method - // using AbstractInterruptibleChannel.closeLock, and also ensures that this - // method is only ever invoked once. Before we get to this method, isOpen - // (which is volatile) will have been set to false. - // - protected void implCloseSelectableChannel() throws IOException { - synchronized (stateLock) { - isInputOpen = false; - isOutputOpen = false; - - closeImpl(); - - // Signal native threads, if needed. If a target thread is not - // currently blocked in an I/O operation then no harm is done since - // the signal handler doesn't actually do anything. - // - if (readerThread != 0) - NativeThread.signal(readerThread); - - if (writerThread != 0) - NativeThread.signal(writerThread); - - // If this channel is not registered then it's safe to close the fd - // immediately since we know at this point that no thread is - // blocked in an I/O operation upon the channel and, since the - // channel is marked closed, no thread will start another such - // operation. If this channel is registered then we don't close - // the fd since it might be in use by a selector. In that case - // closing this channel caused its keys to be cancelled, so the - // last selector to deregister a key for this channel will invoke - // kill() to close the fd. - // - if (!isRegistered()) - kill(); - } - } - - public void kill() throws IOException { - synchronized (stateLock) { - if (state == ST_KILLED) - return; - if (state == ST_UNINITIALIZED) { - state = ST_KILLED; - return; - } - assert !isOpen() && !isRegistered(); - - // Postpone the kill if there is a waiting reader - // or writer thread. See the comments in read() for - // more detailed explanation. - if (readerThread == 0 && writerThread == 0) { - closeImpl(); - state = ST_KILLED; - } else { - state = ST_KILLPENDING; - } - } - } - - /** - * Translates native poll revent ops into a ready operation ops - */ - public boolean translateReadyOps(int ops, int initialOps, - SelectionKeyImpl sk) { - int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes - int oldOps = sk.nioReadyOps(); - int newOps = initialOps; - - if ((ops & PollArrayWrapper.POLLNVAL) != 0) { - // This should only happen if this channel is pre-closed while a - // selection operation is in progress - // ## Throw an error if this channel has not been pre-closed - return false; - } - - if ((ops & (PollArrayWrapper.POLLERR - | PollArrayWrapper.POLLHUP)) != 0) { - newOps = intOps; - sk.nioReadyOps(newOps); - // No need to poll again in checkConnect, - // the error will be detected there - readyToConnect = true; - return (newOps & ~oldOps) != 0; - } - - if (((ops & PollArrayWrapper.POLLIN) != 0) && - ((intOps & SelectionKey.OP_READ) != 0) && - (state == ST_CONNECTED)) - newOps |= SelectionKey.OP_READ; - - if (((ops & PollArrayWrapper.POLLCONN) != 0) && - ((intOps & SelectionKey.OP_CONNECT) != 0) && - ((state == ST_UNCONNECTED) || (state == ST_PENDING))) { - newOps |= SelectionKey.OP_CONNECT; - readyToConnect = true; - } - - if (((ops & PollArrayWrapper.POLLOUT) != 0) && - ((intOps & SelectionKey.OP_WRITE) != 0) && - (state == ST_CONNECTED)) - newOps |= SelectionKey.OP_WRITE; - - sk.nioReadyOps(newOps); - return (newOps & ~oldOps) != 0; - } - - public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) { - return translateReadyOps(ops, sk.nioReadyOps(), sk); - } - - public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) { - return translateReadyOps(ops, 0, sk); - } - - /** - * Translates an interest operation set into a native poll event set - */ - public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) { - int newOps = 0; - if ((ops & SelectionKey.OP_READ) != 0) - newOps |= PollArrayWrapper.POLLIN; - if ((ops & SelectionKey.OP_WRITE) != 0) - newOps |= PollArrayWrapper.POLLOUT; - if ((ops & SelectionKey.OP_CONNECT) != 0) - newOps |= PollArrayWrapper.POLLCONN; - sk.selector.putEventOps(sk, newOps); - } - - public FileDescriptor getFD() { - return fd; - } - - public int getFDVal() { - throw new Error(); - } - - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append(this.getClass().getSuperclass().getName()); - sb.append('['); - if (!isOpen()) - sb.append("closed"); - else { - synchronized (stateLock) { - switch (state) { - case ST_UNCONNECTED: - sb.append("unconnected"); - break; - case ST_PENDING: - sb.append("connection-pending"); - break; - case ST_CONNECTED: - sb.append("connected"); - if (!isInputOpen) - sb.append(" ishut"); - if (!isOutputOpen) - sb.append(" oshut"); - break; - } - if (localAddress() != null) { - sb.append(" local="); - sb.append(localAddress().toString()); - } - if (remoteAddress() != null) { - sb.append(" remote="); - sb.append(remoteAddress().toString()); - } - } - } - sb.append(']'); - return sb.toString(); - } - - - // -- Native methods -- - - private int connectImpl(InetAddress remote, int remotePort, int trafficClass) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - cli.System.Net.IPEndPoint ep = new cli.System.Net.IPEndPoint(SocketUtil.getAddressFromInetAddress(remote), remotePort); - if (isBlocking()) - { - fd.getSocket().Connect(ep); - return 1; - } - else - { - asyncConnect = fd.getSocket().BeginConnect(ep, null, null); - return IOStatus.UNAVAILABLE; - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new ConnectException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private int checkConnect(FileDescriptor fd, boolean block, boolean ready) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - if (block || ready || asyncConnect.get_IsCompleted()) - { - cli.System.IAsyncResult res = asyncConnect; - asyncConnect = null; - fd.getSocket().EndConnect(res); - // work around for blocking issue - fd.getSocket().set_Blocking(isBlocking()); - return 1; - } - else - { - return IOStatus.UNAVAILABLE; - } - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw new ConnectException(x.getMessage()); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private static /*native*/ int sendOutOfBandData(FileDescriptor fd, byte data) throws IOException - { - throw new NotYetImplementedError(); //TODO JDK7 - } - - private static void shutdown(FileDescriptor fd, int how) throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - fd.getSocket().Shutdown(cli.System.Net.Sockets.SocketShutdown.wrap(how == SHUT_RD ? cli.System.Net.Sockets.SocketShutdown.Receive : cli.System.Net.Sockets.SocketShutdown.Send)); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - - private void closeImpl() throws IOException - { - try - { - if (false) throw new cli.System.Net.Sockets.SocketException(); - if (false) throw new cli.System.ObjectDisposedException(""); - fd.getSocket().Close(); - } - catch (cli.System.Net.Sockets.SocketException x) - { - throw SocketUtil.convertSocketExceptionToIOException(x); - } - catch (cli.System.ObjectDisposedException x1) - { - throw new SocketException("Socket is closed"); - } - } - -} - -// temporary compilation stubs -class PollArrayWrapper -{ - static final short POLLIN = 0x0001; - static final short POLLOUT = 0x0004; - static final short POLLERR = 0x0008; - static final short POLLHUP = 0x0010; - static final short POLLNVAL = 0x0020; - static final short POLLREMOVE = 0x0800; - static final short POLLCONN = 0x0002; -} diff --git a/openjdk/sun/nio/ch/SocketDispatcher.java b/openjdk/sun/nio/ch/SocketDispatcher.java new file mode 100644 index 00000000..3d04dd1c --- /dev/null +++ b/openjdk/sun/nio/ch/SocketDispatcher.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.nio.ch; + +import java.io.*; + +/** + * Allows different platforms to call different native methods + * for read and write operations. + */ + +class SocketDispatcher extends NativeDispatcher +{ + + static { + Util.load(); + } + + int read(FileDescriptor fd, long address, int len) throws IOException { + throw new ikvm.internal.NotYetImplementedError(); + } + + long readv(FileDescriptor fd, long address, int len) throws IOException { + throw new ikvm.internal.NotYetImplementedError(); + } + + int write(FileDescriptor fd, long address, int len) throws IOException { + throw new ikvm.internal.NotYetImplementedError(); + } + + long writev(FileDescriptor fd, long address, int len) throws IOException { + throw new ikvm.internal.NotYetImplementedError(); + } + + void close(FileDescriptor fd) throws IOException { + } + + void preClose(FileDescriptor fd) throws IOException { + try + { + if (false) throw new cli.System.Net.Sockets.SocketException(); + if (false) throw new cli.System.ObjectDisposedException(""); + fd.getSocket().Close(); + } + catch (cli.System.Net.Sockets.SocketException x) + { + throw java.net.SocketUtil.convertSocketExceptionToIOException(x); + } + catch (cli.System.ObjectDisposedException x1) + { + throw new java.net.SocketException("Socket is closed"); + } + } +} diff --git a/openjdk/sun/nio/ch/SocketOptionRegistry.java b/openjdk/sun/nio/ch/SocketOptionRegistry.java new file mode 100644 index 00000000..83887fbc --- /dev/null +++ b/openjdk/sun/nio/ch/SocketOptionRegistry.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.nio.ch; +import java.net.SocketOption; +import java.net.StandardSocketOptions; +import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; +import java.util.Map; +import java.util.HashMap; +import cli.System.Net.Sockets.SocketOptionLevel; +import cli.System.Net.Sockets.SocketOptionName; + +class SocketOptionRegistry { + private SocketOptionRegistry() { } + private static class RegistryKey { + private final SocketOption<?> name; + private final ProtocolFamily family; + RegistryKey(SocketOption<?> name, ProtocolFamily family) { + this.name = name; + this.family = family; + } + public int hashCode() { + return name.hashCode() + family.hashCode(); + } + public boolean equals(Object ob) { + if (ob == null) return false; + if (!(ob instanceof RegistryKey)) return false; + RegistryKey other = (RegistryKey)ob; + if (this.name != other.name) return false; + if (this.family != other.family) return false; + return true; + } + } + private static class LazyInitialization { + static final Map<RegistryKey,OptionKey> options = options(); + private static Map<RegistryKey,OptionKey> options() { + Map<RegistryKey,OptionKey> map = + new HashMap<RegistryKey,OptionKey>(); + map.put(new RegistryKey(StandardSocketOptions.SO_BROADCAST, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.Broadcast)); + map.put(new RegistryKey(StandardSocketOptions.SO_KEEPALIVE, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.KeepAlive)); + map.put(new RegistryKey(StandardSocketOptions.SO_LINGER, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.Linger)); + map.put(new RegistryKey(StandardSocketOptions.SO_SNDBUF, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.SendBuffer)); + map.put(new RegistryKey(StandardSocketOptions.SO_RCVBUF, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer)); + map.put(new RegistryKey(StandardSocketOptions.SO_REUSEADDR, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress)); + map.put(new RegistryKey(StandardSocketOptions.TCP_NODELAY, Net.UNSPEC), new OptionKey(SocketOptionLevel.Tcp, SocketOptionName.NoDelay)); + map.put(new RegistryKey(StandardSocketOptions.IP_TOS, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.TypeOfService)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_IF, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.MulticastInterface)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_TTL, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_LOOP, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_IF, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, SocketOptionName.MulticastInterface)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_TTL, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, SocketOptionName.IpTimeToLive)); + map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_LOOP, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)); + map.put(new RegistryKey(ExtendedSocketOption.SO_OOBINLINE, Net.UNSPEC), new OptionKey(SocketOptionLevel.Socket, SocketOptionName.OutOfBandInline)); + return map; + } + } + public static OptionKey findOption(SocketOption<?> name, ProtocolFamily family) { + RegistryKey key = new RegistryKey(name, family); + return LazyInitialization.options.get(key); + } +} diff --git a/openjdk/sun/nio/ch/Util.java b/openjdk/sun/nio/ch/Util.java index e074c5b2..475c1b9b 100644 --- a/openjdk/sun/nio/ch/Util.java +++ b/openjdk/sun/nio/ch/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,10 @@ package sun.nio.ch; import java.lang.ref.SoftReference; import java.lang.reflect.*; import java.io.IOException; +import java.io.FileDescriptor; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.*; -import java.nio.channels.spi.*; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; @@ -65,10 +65,12 @@ class Util { } // Per-thread cached selector - private static ThreadLocal localSelector = new ThreadLocal(); + private static ThreadLocal<SoftReference<SelectorWrapper>> localSelector + = new ThreadLocal<SoftReference<SelectorWrapper>>(); // Hold a reference to the selWrapper object to prevent it from // being cleaned when the temporary selector wrapped is on lease. - private static ThreadLocal localSelectorWrapper = new ThreadLocal(); + private static ThreadLocal<SelectorWrapper> localSelectorWrapper + = new ThreadLocal<SelectorWrapper>(); // When finished, invoker must ensure that selector is empty // by cancelling any related keys and explicitly releasing @@ -76,18 +78,18 @@ class Util { static Selector getTemporarySelector(SelectableChannel sc) throws IOException { - SoftReference ref = (SoftReference)localSelector.get(); + SoftReference<SelectorWrapper> ref = localSelector.get(); SelectorWrapper selWrapper = null; Selector sel = null; if (ref == null - || ((selWrapper = (SelectorWrapper) ref.get()) == null) + || ((selWrapper = ref.get()) == null) || ((sel = selWrapper.get()) == null) || (sel.provider() != sc.provider())) { sel = sc.provider().openSelector(); - localSelector.set(new SoftReference(new SelectorWrapper(sel))); - } else { - localSelectorWrapper.set(selWrapper); + selWrapper = new SelectorWrapper(sel); + localSelector.set(new SoftReference<SelectorWrapper>(selWrapper)); } + localSelectorWrapper.set(selWrapper); return sel; } @@ -152,13 +154,14 @@ class Util { private static volatile Constructor directByteBufferConstructor = null; private static void initDBBConstructor() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + public Void run() { try { - Class cl = Class.forName("java.nio.DirectByteBuffer"); + Class<?> cl = Class.forName("java.nio.DirectByteBuffer"); Constructor ctor = cl.getDeclaredConstructor( new Class[] { int.class, long.class, + FileDescriptor.class, Runnable.class }); ctor.setAccessible(true); directByteBufferConstructor = ctor; @@ -176,6 +179,7 @@ class Util { } static MappedByteBuffer newMappedByteBuffer(int size, long addr, + FileDescriptor fd, Runnable unmapper) { MappedByteBuffer dbb; @@ -185,6 +189,7 @@ class Util { dbb = (MappedByteBuffer)directByteBufferConstructor.newInstance( new Object[] { new Integer(size), new Long(addr), + fd, unmapper }); } catch (InstantiationException e) { throw new InternalError(); @@ -199,13 +204,14 @@ class Util { private static volatile Constructor directByteBufferRConstructor = null; private static void initDBBRConstructor() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + public Void run() { try { - Class cl = Class.forName("java.nio.DirectByteBufferR"); + Class<?> cl = Class.forName("java.nio.DirectByteBufferR"); Constructor ctor = cl.getDeclaredConstructor( new Class[] { int.class, long.class, + FileDescriptor.class, Runnable.class }); ctor.setAccessible(true); directByteBufferRConstructor = ctor; @@ -223,6 +229,7 @@ class Util { } static MappedByteBuffer newMappedByteBufferR(int size, long addr, + FileDescriptor fd, Runnable unmapper) { MappedByteBuffer dbb; @@ -232,6 +239,7 @@ class Util { dbb = (MappedByteBuffer)directByteBufferRConstructor.newInstance( new Object[] { new Integer(size), new Long(addr), + fd, unmapper }); } catch (InstantiationException e) { throw new InternalError(); |