Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2011-07-15 13:05:26 +0400
committerjfrijters <jfrijters>2011-07-15 13:05:26 +0400
commit20464c682cbc4ab4b937774b1872928179870d74 (patch)
tree0df9c343c8ac6cb93ac55eec6e836a06e414b267 /openjdk/sun/nio/ch
parentafeabe4188bd04bcfc74b141664c294fc57c4b0a (diff)
Updated bulk of java.nio to OpenJDK 7.
Diffstat (limited to 'openjdk/sun/nio/ch')
-rw-r--r--openjdk/sun/nio/ch/DatagramChannelImpl.java465
-rw-r--r--openjdk/sun/nio/ch/DefaultAsynchronousChannelProvider.java5
-rw-r--r--openjdk/sun/nio/ch/FileChannelImpl.java19
-rw-r--r--openjdk/sun/nio/ch/IOUtil.java134
-rw-r--r--openjdk/sun/nio/ch/Net.java627
-rw-r--r--openjdk/sun/nio/ch/ServerSocketChannelImpl.java443
-rw-r--r--openjdk/sun/nio/ch/SocketChannelImpl.java1089
-rw-r--r--openjdk/sun/nio/ch/SocketDispatcher.java77
-rw-r--r--openjdk/sun/nio/ch/SocketOptionRegistry.java86
-rw-r--r--openjdk/sun/nio/ch/Util.java38
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();