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:
Diffstat (limited to 'openjdk/sun/nio/ch/DatagramChannelImpl.java')
-rw-r--r--openjdk/sun/nio/ch/DatagramChannelImpl.java1113
1 files changed, 0 insertions, 1113 deletions
diff --git a/openjdk/sun/nio/ch/DatagramChannelImpl.java b/openjdk/sun/nio/ch/DatagramChannelImpl.java
deleted file mode 100644
index 08cc5c95..00000000
--- a/openjdk/sun/nio/ch/DatagramChannelImpl.java
+++ /dev/null
@@ -1,1113 +0,0 @@
-/*
- * Copyright (c) 2001, 2012, 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.net.*;
-import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-import java.util.*;
-import sun.net.ResourceManager;
-
-
-/**
- * An implementation of DatagramChannels.
- */
-
-class DatagramChannelImpl
- extends DatagramChannel
- implements SelChImpl
-{
-
- // Used to make native read and write calls
- private static NativeDispatcher nd = new SocketDispatcher();
-
- // Our file descriptor
- 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;
-
- // IDs of native threads doing reads and writes, for signalling
- private volatile long readerThread = 0;
- private volatile long writerThread = 0;
-
- // Cached InetAddress and port for unconnected DatagramChannels
- // used by receive0
- private InetAddress cachedSenderInetAddress;
- private int cachedSenderPort;
-
- // 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 (does not necessarily increase monotonically)
- private static final int ST_UNINITIALIZED = -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 InetSocketAddress localAddress;
- private InetSocketAddress remoteAddress;
-
- // Our socket adaptor, if any
- private DatagramSocket socket;
-
- // Multicast support
- private MembershipRegistry registry;
-
- // set true when socket is bound and SO_REUSEADDRESS is emulated
- private boolean reuseAddressEmulated;
-
- // set true/false when socket is already bound and SO_REUSEADDR is emulated
- private boolean isReuseAddress;
-
- // -- End of fields protected by stateLock
-
-
- public DatagramChannelImpl(SelectorProvider sp)
- throws IOException
- {
- super(sp);
- ResourceManager.beforeUdpCreate();
- try {
- this.family = Net.isIPv6Available() ?
- StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
- this.fd = Net.socket(family, false);
- this.fdVal = IOUtil.fdVal(fd);
- this.state = ST_UNCONNECTED;
- } catch (IOException ioe) {
- ResourceManager.afterUdpClose();
- throw ioe;
- }
- }
-
- public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family)
- throws IOException
- {
- super(sp);
- if ((family != StandardProtocolFamily.INET) &&
- (family != StandardProtocolFamily.INET6))
- {
- if (family == null)
- throw new NullPointerException("'family' is null");
- else
- throw new UnsupportedOperationException("Protocol family not supported");
- }
- if (family == StandardProtocolFamily.INET6) {
- if (!Net.isIPv6Available()) {
- throw new UnsupportedOperationException("IPv6 not available");
- }
- }
- this.family = family;
- this.fd = Net.socket(family, false);
- this.fdVal = IOUtil.fdVal(fd);
- this.state = ST_UNCONNECTED;
- }
-
- public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
- throws IOException
- {
- super(sp);
- this.family = Net.isIPv6Available() ?
- StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
- this.fd = fd;
- this.fdVal = IOUtil.fdVal(fd);
- this.state = ST_UNCONNECTED;
- this.localAddress = Net.localAddress(fd);
- }
-
- public DatagramSocket socket() {
- synchronized (stateLock) {
- if (socket == null)
- socket = DatagramSocketAdaptor.create(this);
- return socket;
- }
- }
-
- @Override
- public SocketAddress getLocalAddress() throws IOException {
- synchronized (stateLock) {
- if (!isOpen())
- throw new ClosedChannelException();
- return Net.getRevealedLocalAddress(localAddress);
- }
- }
-
- @Override
- public SocketAddress getRemoteAddress() throws IOException {
- synchronized (stateLock) {
- if (!isOpen())
- throw new ClosedChannelException();
- return remoteAddress;
- }
- }
-
- @Override
- public <T> DatagramChannel 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) {
- ensureOpen();
-
- if (name == StandardSocketOptions.IP_TOS) {
- // IPv4 only; no-op for IPv6
- if (family == StandardProtocolFamily.INET) {
- Net.setSocketOption(fd, family, name, value);
- }
- return this;
- }
-
- if (name == StandardSocketOptions.IP_MULTICAST_TTL ||
- name == StandardSocketOptions.IP_MULTICAST_LOOP)
- {
- // options are protocol dependent
- Net.setSocketOption(fd, family, name, value);
- return this;
- }
-
- if (name == StandardSocketOptions.IP_MULTICAST_IF) {
- if (value == null)
- throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'");
- NetworkInterface interf = (NetworkInterface)value;
- if (family == StandardProtocolFamily.INET6) {
- int index = interf.getIndex();
- if (index == -1)
- throw new IOException("Network interface cannot be identified");
- Net.setInterface6(fd, index);
- } 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 targetAddress = Net.inet4AsInt(target);
- Net.setInterface4(fd, targetAddress);
- }
- return this;
- }
- if (name == StandardSocketOptions.SO_REUSEADDR &&
- Net.useExclusiveBind() && localAddress != null)
- {
- reuseAddressEmulated = true;
- this.isReuseAddress = (Boolean)value;
- }
-
- // remaining options don't need any special handling
- Net.setSocketOption(fd, Net.UNSPEC, name, value);
- return this;
- }
- }
-
- @Override
- @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) {
- ensureOpen();
-
- if (name == StandardSocketOptions.IP_TOS) {
- // IPv4 only; always return 0 on IPv6
- if (family == StandardProtocolFamily.INET) {
- return (T) Net.getSocketOption(fd, family, name);
- } else {
- return (T) Integer.valueOf(0);
- }
- }
-
- if (name == StandardSocketOptions.IP_MULTICAST_TTL ||
- name == StandardSocketOptions.IP_MULTICAST_LOOP)
- {
- return (T) Net.getSocketOption(fd, family, name);
- }
-
- if (name == StandardSocketOptions.IP_MULTICAST_IF) {
- if (family == StandardProtocolFamily.INET) {
- int address = Net.getInterface4(fd);
- if (address == 0)
- return null; // default interface
-
- InetAddress ia = Net.inet4FromInt(address);
- NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
- if (ni == null)
- throw new IOException("Unable to map address to interface");
- return (T) ni;
- } else {
- int index = Net.getInterface6(fd);
- if (index == 0)
- return null; // default interface
-
- NetworkInterface ni = NetworkInterface.getByIndex(index);
- if (ni == null)
- throw new IOException("Unable to map index to interface");
- return (T) ni;
- }
- }
-
- if (name == StandardSocketOptions.SO_REUSEADDR &&
- reuseAddressEmulated)
- {
- return (T)Boolean.valueOf(isReuseAddress);
- }
-
- // no 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_REUSEADDR);
- set.add(StandardSocketOptions.SO_BROADCAST);
- set.add(StandardSocketOptions.IP_TOS);
- set.add(StandardSocketOptions.IP_MULTICAST_IF);
- set.add(StandardSocketOptions.IP_MULTICAST_TTL);
- set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
- return Collections.unmodifiableSet(set);
- }
- }
-
- @Override
- public final Set<SocketOption<?>> supportedOptions() {
- return DefaultOptionsHolder.defaultOptions;
- }
-
- private void ensureOpen() throws ClosedChannelException {
- if (!isOpen())
- throw new ClosedChannelException();
- }
-
- SocketAddress sender; // Set by receive0 (## ugh)
-
- public SocketAddress receive(ByteBuffer dst) throws IOException {
- if (dst.isReadOnly())
- throw new IllegalArgumentException("Read-only buffer");
- if (dst == null)
- throw new NullPointerException();
- synchronized (readLock) {
- ensureOpen();
- // Socket was not bound before attempting receive
- if (localAddress() == null)
- bind(null);
- int n = 0;
- ByteBuffer bb = null;
- try {
- begin();
- if (!isOpen())
- return null;
- SecurityManager security = System.getSecurityManager();
- readerThread = NativeThread.current();
- if (isConnected() || (security == null)) {
- do {
- n = receive(fd, dst);
- } while ((n == IOStatus.INTERRUPTED) && isOpen());
- if (n == IOStatus.UNAVAILABLE)
- return null;
- } else {
- bb = ByteBuffer.allocate(dst.remaining());
- for (;;) {
- do {
- n = receive(fd, bb);
- } while ((n == IOStatus.INTERRUPTED) && isOpen());
- if (n == IOStatus.UNAVAILABLE)
- return null;
- InetSocketAddress isa = (InetSocketAddress)sender;
- try {
- security.checkAccept(
- isa.getAddress().getHostAddress(),
- isa.getPort());
- } catch (SecurityException se) {
- // Ignore packet
- bb.clear();
- n = 0;
- continue;
- }
- bb.flip();
- dst.put(bb);
- break;
- }
- }
- return sender;
- } finally {
- readerThread = 0;
- end((n > 0) || (n == IOStatus.UNAVAILABLE));
- assert IOStatus.check(n);
- }
- }
- }
-
- private int receive(FileDescriptor fd, ByteBuffer dst)
- throws IOException
- {
- int pos = dst.position();
- int lim = dst.limit();
- assert (pos <= lim);
- int rem = (pos <= lim ? lim - pos : 0);
- if (dst.hasArray() && rem > 0)
- return receiveIntoManagedBuffer(fd, dst, rem, pos);
-
- // Substitute a managed buffer. If the supplied buffer is empty
- // we must instead use a nonempty buffer, otherwise the call
- // will not block waiting for a datagram on some platforms.
- int newSize = Math.max(rem, 1);
- ByteBuffer bb = ByteBuffer.allocate(newSize);
- try {
- int n = receiveIntoManagedBuffer(fd, bb, newSize, 0);
- bb.flip();
- if (n > 0 && rem > 0)
- dst.put(bb);
- return n;
- } finally {
- }
- }
-
- private int receiveIntoManagedBuffer(FileDescriptor fd, ByteBuffer bb,
- int rem, int pos)
- throws IOException
- {
- int n = receive0(fd, bb.array(), bb.arrayOffset() + pos, rem,
- isConnected());
- if (n > 0)
- bb.position(pos + n);
- return n;
- }
-
- public int send(ByteBuffer src, SocketAddress target)
- throws IOException
- {
- if (src == null)
- throw new NullPointerException();
-
- synchronized (writeLock) {
- ensureOpen();
- InetSocketAddress isa = Net.checkAddress(target);
- InetAddress ia = isa.getAddress();
- if (ia == null)
- throw new IOException("Target address not resolved");
- synchronized (stateLock) {
- if (!isConnected()) {
- if (target == null)
- throw new NullPointerException();
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- if (ia.isMulticastAddress()) {
- sm.checkMulticast(ia);
- } else {
- sm.checkConnect(ia.getHostAddress(),
- isa.getPort());
- }
- }
- } else { // Connected case; Check address then write
- if (!target.equals(remoteAddress)) {
- throw new IllegalArgumentException(
- "Connected address not equal to target address");
- }
- return write(src);
- }
- }
-
- int n = 0;
- try {
- begin();
- if (!isOpen())
- return 0;
- writerThread = NativeThread.current();
- do {
- n = send(fd, src, isa);
- } while ((n == IOStatus.INTERRUPTED) && isOpen());
-
- synchronized (stateLock) {
- if (isOpen() && (localAddress == null)) {
- localAddress = Net.localAddress(fd);
- }
- }
- return IOStatus.normalize(n);
- } finally {
- writerThread = 0;
- end((n > 0) || (n == IOStatus.UNAVAILABLE));
- assert IOStatus.check(n);
- }
- }
- }
-
- private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target)
- throws IOException
- {
- if (src.hasArray())
- return sendFromManagedBuffer(fd, src, target);
-
- // Substitute a managed buffer
- int pos = src.position();
- int lim = src.limit();
- assert (pos <= lim);
- int rem = (pos <= lim ? lim - pos : 0);
-
- ByteBuffer bb = ByteBuffer.allocate(rem);
- try {
- bb.put(src);
- bb.flip();
- // Do not update src until we see how many bytes were written
- src.position(pos);
-
- int n = sendFromManagedBuffer(fd, bb, target);
- if (n > 0) {
- // now update src
- src.position(pos + n);
- }
- return n;
- } finally {
- }
- }
-
- private int sendFromManagedBuffer(FileDescriptor fd, ByteBuffer bb,
- InetSocketAddress target)
- throws IOException
- {
- int pos = bb.position();
- int lim = bb.limit();
- assert (pos <= lim);
- int rem = (pos <= lim ? lim - pos : 0);
-
- boolean preferIPv6 = (family != StandardProtocolFamily.INET);
- int written;
- try {
- written = send0(preferIPv6, fd, bb.array(), bb.arrayOffset() + pos,
- rem, target.getAddress(), target.getPort());
- } catch (PortUnreachableException pue) {
- if (isConnected())
- throw pue;
- written = rem;
- }
- if (written > 0)
- bb.position(pos + written);
- return written;
- }
-
- public int read(ByteBuffer buf) throws IOException {
- if (buf == null)
- throw new NullPointerException();
- synchronized (readLock) {
- synchronized (stateLock) {
- ensureOpen();
- if (!isConnected())
- throw new NotYetConnectedException();
- }
- int n = 0;
- try {
- begin();
- if (!isOpen())
- return 0;
- readerThread = NativeThread.current();
- do {
- n = IOUtil.read(fd, buf, -1, nd, readLock);
- } while ((n == IOStatus.INTERRUPTED) && isOpen());
- return IOStatus.normalize(n);
- } finally {
- readerThread = 0;
- end((n > 0) || (n == IOStatus.UNAVAILABLE));
- 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();
- synchronized (readLock) {
- synchronized (stateLock) {
- ensureOpen();
- if (!isConnected())
- throw new NotYetConnectedException();
- }
- long n = 0;
- try {
- begin();
- if (!isOpen())
- return 0;
- readerThread = NativeThread.current();
- do {
- n = IOUtil.read(fd, dsts, offset, length, nd);
- } while ((n == IOStatus.INTERRUPTED) && isOpen());
- return IOStatus.normalize(n);
- } finally {
- readerThread = 0;
- end((n > 0) || (n == IOStatus.UNAVAILABLE));
- assert IOStatus.check(n);
- }
- }
- }
-
- public int write(ByteBuffer buf) throws IOException {
- if (buf == null)
- throw new NullPointerException();
- synchronized (writeLock) {
- synchronized (stateLock) {
- ensureOpen();
- if (!isConnected())
- throw new NotYetConnectedException();
- }
- int n = 0;
- try {
- begin();
- if (!isOpen())
- return 0;
- writerThread = NativeThread.current();
- do {
- n = IOUtil.write(fd, buf, -1, nd, writeLock);
- } while ((n == IOStatus.INTERRUPTED) && isOpen());
- return IOStatus.normalize(n);
- } finally {
- writerThread = 0;
- end((n > 0) || (n == IOStatus.UNAVAILABLE));
- 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();
- synchronized (writeLock) {
- synchronized (stateLock) {
- ensureOpen();
- if (!isConnected())
- throw new NotYetConnectedException();
- }
- long n = 0;
- try {
- begin();
- if (!isOpen())
- return 0;
- writerThread = NativeThread.current();
- do {
- n = IOUtil.write(fd, srcs, offset, length, nd);
- } while ((n == IOStatus.INTERRUPTED) && isOpen());
- return IOStatus.normalize(n);
- } finally {
- writerThread = 0;
- end((n > 0) || (n == IOStatus.UNAVAILABLE));
- assert IOStatus.check(n);
- }
- }
- }
-
- protected void implConfigureBlocking(boolean block) throws IOException {
- IOUtil.configureBlocking(fd, block);
- }
-
- public SocketAddress localAddress() {
- synchronized (stateLock) {
- return localAddress;
- }
- }
-
- public SocketAddress remoteAddress() {
- synchronized (stateLock) {
- return remoteAddress;
- }
- }
-
- @Override
- public DatagramChannel bind(SocketAddress local) throws IOException {
- synchronized (readLock) {
- synchronized (writeLock) {
- synchronized (stateLock) {
- ensureOpen();
- if (localAddress != null)
- throw new AlreadyBoundException();
- InetSocketAddress isa;
- if (local == null) {
- // only Inet4Address allowed with IPv4 socket
- if (family == StandardProtocolFamily.INET) {
- isa = new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0);
- } else {
- 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) {
- sm.checkListen(isa.getPort());
- }
- Net.bind(family, fd, isa.getAddress(), isa.getPort());
- localAddress = Net.localAddress(fd);
- }
- }
- }
- return this;
- }
-
- public boolean isConnected() {
- synchronized (stateLock) {
- return (state == ST_CONNECTED);
- }
- }
-
- void ensureOpenAndUnconnected() throws IOException { // package-private
- synchronized (stateLock) {
- if (!isOpen())
- throw new ClosedChannelException();
- if (state != ST_UNCONNECTED)
- throw new IllegalStateException("Connect already invoked");
- }
- }
-
- @Override
- public DatagramChannel connect(SocketAddress sa) throws IOException {
- int localPort = 0;
-
- synchronized(readLock) {
- synchronized(writeLock) {
- synchronized (stateLock) {
- ensureOpenAndUnconnected();
- InetSocketAddress isa = Net.checkAddress(sa);
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkConnect(isa.getAddress().getHostAddress(),
- isa.getPort());
- int n = Net.connect(family,
- fd,
- isa.getAddress(),
- isa.getPort());
- if (n <= 0)
- throw new Error(); // Can't happen
-
- // Connection succeeded; disallow further invocation
- state = ST_CONNECTED;
- remoteAddress = isa;
- sender = isa;
- cachedSenderInetAddress = isa.getAddress();
- cachedSenderPort = isa.getPort();
-
- // set or refresh local address
- localAddress = Net.localAddress(fd);
- }
- }
- }
- return this;
- }
-
- public DatagramChannel disconnect() throws IOException {
- synchronized(readLock) {
- synchronized(writeLock) {
- synchronized (stateLock) {
- if (!isConnected() || !isOpen())
- return this;
- InetSocketAddress isa = remoteAddress;
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkConnect(isa.getAddress().getHostAddress(),
- isa.getPort());
- boolean isIPv6 = (family == StandardProtocolFamily.INET6);
- disconnect0(fd, isIPv6);
- remoteAddress = null;
- state = ST_UNCONNECTED;
-
- // refresh local address
- localAddress = Net.localAddress(fd);
- }
- }
- }
- return this;
- }
-
- /**
- * Joins channel's socket to the given group/interface and
- * optional source address.
- */
- private MembershipKey innerJoin(InetAddress group,
- NetworkInterface interf,
- InetAddress source)
- throws IOException
- {
- 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
- {
- return innerJoin(group, interf, null);
- }
-
- @Override
- public MembershipKey join(InetAddress group,
- NetworkInterface interf,
- InetAddress source)
- throws IOException
- {
- if (source == null)
- 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) {
- if (state != ST_KILLED)
- 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);
- if ((th = writerThread) != 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();
- nd.close(fd);
- 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_READ) != 0))
- newOps |= SelectionKey.OP_READ;
-
- if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
- ((intOps & SelectionKey.OP_WRITE) != 0))
- 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.POLLIN;
- sk.selector.putEventOps(sk, newOps);
- }
-
- public FileDescriptor getFD() {
- return fd;
- }
-
- public int getFDVal() {
- return fdVal;
- }
-
-
- // -- Native methods --
-
- private static native void initIDs();
-
- private static native void disconnect0(FileDescriptor fd, boolean isIPv6)
- throws IOException;
-
- private native int receive0(FileDescriptor fd, byte[] buf, int pos, int len,
- boolean connected)
- throws IOException;
-
- private native int send0(boolean preferIPv6, FileDescriptor fd, byte[] buf, int pos,
- int len, InetAddress addr, int port)
- throws IOException;
-
- static {
- Util.load();
- initIDs();
- }
-
-}