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/DatagramChannelImpl.java
parentafeabe4188bd04bcfc74b141664c294fc57c4b0a (diff)
Updated bulk of java.nio to OpenJDK 7.
Diffstat (limited to 'openjdk/sun/nio/ch/DatagramChannelImpl.java')
-rw-r--r--openjdk/sun/nio/ch/DatagramChannelImpl.java465
1 files changed, 285 insertions, 180 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;
- }
}