diff options
author | smallsql <smallsql> | 2011-07-10 13:15:37 +0400 |
---|---|---|
committer | smallsql <smallsql> | 2011-07-10 13:15:37 +0400 |
commit | 872f562f685f23d2b8f4fa6e07e4d3ece3ba07a5 (patch) | |
tree | d198205ae5e9031ec9894c098b71c49812098975 /openjdk/sun | |
parent | 5314bdefb22153c8ceb89a7bc0dc29f6407c8beb (diff) |
Add methods in DatagramChannelImpl for Java 7
Diffstat (limited to 'openjdk/sun')
-rw-r--r-- | openjdk/sun/nio/ch/DatagramChannelImpl.java | 198 | ||||
-rw-r--r-- | openjdk/sun/nio/ch/Net.java | 104 |
2 files changed, 300 insertions, 2 deletions
diff --git a/openjdk/sun/nio/ch/DatagramChannelImpl.java b/openjdk/sun/nio/ch/DatagramChannelImpl.java index 6cbda443..72f62adf 100644 --- a/openjdk/sun/nio/ch/DatagramChannelImpl.java +++ b/openjdk/sun/nio/ch/DatagramChannelImpl.java @@ -33,6 +33,9 @@ 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 sun.net.ResourceManager; @@ -55,6 +58,9 @@ class DatagramChannelImpl // Our file descriptor FileDescriptor fd = null; + // 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; @@ -102,6 +108,8 @@ class DatagramChannelImpl super(sp); ResourceManager.beforeUdpCreate(); try { + this.family = Net.isIPv6Available() ? + StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; this.fd = Net.socket(false); this.state = ST_UNCONNECTED; try @@ -123,6 +131,20 @@ class DatagramChannelImpl 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; throw new NotYetImplementedError(); //TODO JDK7 } @@ -130,6 +152,8 @@ class DatagramChannelImpl throws IOException { super(sp); + this.family = Net.isIPv6Available() ? + StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; this.fd = fd; this.state = ST_UNCONNECTED; } @@ -142,6 +166,151 @@ class DatagramChannelImpl } } + 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> 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; + } + + // remaining options don't need any 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) { + 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; + } + } + + // 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); + } + } + + public final Set<SocketOption<?>> supportedOptions() { + return DefaultOptionsHolder.defaultOptions; + } + private void ensureOpen() throws ClosedChannelException { if (!isOpen()) throw new ClosedChannelException(); @@ -529,6 +698,35 @@ class DatagramChannelImpl 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 + { + throw new NotYetImplementedError(); //TODO JDK7 + } + + public MembershipKey join(InetAddress group, + NetworkInterface interf) + throws IOException + { + return innerJoin(group, interf, null); + } + + 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); + } + protected void implCloseSelectableChannel() throws IOException { synchronized (stateLock) { closeImpl(); diff --git a/openjdk/sun/nio/ch/Net.java b/openjdk/sun/nio/ch/Net.java index 1d7fa47c..0b0ef558 100644 --- a/openjdk/sun/nio/ch/Net.java +++ b/openjdk/sun/nio/ch/Net.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -39,10 +39,13 @@ import cli.System.Net.Sockets.SocketShutdown; import ikvm.internal.NotYetImplementedError; import ikvm.lang.CIL; import java.io.*; -import java.lang.reflect.*; 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 @@ -508,6 +511,84 @@ class Net { // package-private translateException(x, false); } + /** + * Returns any IPv4 address of the given network interface, or + * null if the interface does not have any IPv4 addresses. + */ + static Inet4Address anyInet4Address(final NetworkInterface interf) { + return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() { + public Inet4Address run() { + Enumeration<InetAddress> addrs = interf.getInetAddresses(); + while (addrs.hasMoreElements()) { + InetAddress addr = addrs.nextElement(); + if (addr instanceof Inet4Address) { + return (Inet4Address)addr; + } + } + return null; + } + }); + } + + /** + * Returns an IPv4 address as an int. + */ + static int inet4AsInt(InetAddress ia) { + if (ia instanceof Inet4Address) { + byte[] addr = ia.getAddress(); + int address = addr[3] & 0xFF; + address |= ((addr[2] << 8) & 0xFF00); + address |= ((addr[1] << 16) & 0xFF0000); + address |= ((addr[0] << 24) & 0xFF000000); + return address; + } + throw new AssertionError("Should not reach here"); + } + + /** + * Returns an InetAddress from the given IPv4 address + * represented as an int. + */ + static InetAddress inet4FromInt(int address) { + byte[] addr = new byte[4]; + addr[0] = (byte) ((address >>> 24) & 0xFF); + addr[1] = (byte) ((address >>> 16) & 0xFF); + addr[2] = (byte) ((address >>> 8) & 0xFF); + addr[3] = (byte) (address & 0xFF); + try { + return InetAddress.getByAddress(addr); + } catch (UnknownHostException uhe) { + throw new AssertionError("Should not reach here"); + } + } + + /** + * Returns an IPv6 address as a byte array + */ + static byte[] inet6AsByteArray(InetAddress ia) { + if (ia instanceof Inet6Address) { + return ia.getAddress(); + } + + // need to construct IPv4-mapped address + if (ia instanceof Inet4Address) { + byte[] ip4address = ia.getAddress(); + byte[] address = new byte[16]; + address[10] = (byte)0xff; + address[11] = (byte)0xff; + address[12] = ip4address[0]; + address[13] = ip4address[1]; + address[14] = ip4address[2]; + address[15] = ip4address[3]; + return address; + } + + throw new AssertionError("Should not reach here"); + } + + // -- Socket options + + static void setSocketOption(FileDescriptor fd, ProtocolFamily family, SocketOption<?> name, Object value) throws IOException @@ -611,4 +692,23 @@ class Net { // package-private throw new NotYetImplementedError(); //TODO JDK7 } + static /*native*/ void setInterface4(FileDescriptor fd, int interf) throws IOException + { + throw new NotYetImplementedError(); //TODO JDK7 + } + + static /*native*/ int getInterface4(FileDescriptor fd) throws IOException + { + throw new NotYetImplementedError(); //TODO JDK7 + } + + static /*native*/ void setInterface6(FileDescriptor fd, int index) throws IOException + { + throw new NotYetImplementedError(); //TODO JDK7 + } + + static /*native*/ int getInterface6(FileDescriptor fd) throws IOException + { + throw new NotYetImplementedError(); //TODO JDK7 + } } |