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:
authorsmallsql <smallsql>2011-07-10 13:15:37 +0400
committersmallsql <smallsql>2011-07-10 13:15:37 +0400
commit872f562f685f23d2b8f4fa6e07e4d3ece3ba07a5 (patch)
treed198205ae5e9031ec9894c098b71c49812098975 /openjdk/sun/nio/ch
parent5314bdefb22153c8ceb89a7bc0dc29f6407c8beb (diff)
Add methods in DatagramChannelImpl for Java 7
Diffstat (limited to 'openjdk/sun/nio/ch')
-rw-r--r--openjdk/sun/nio/ch/DatagramChannelImpl.java198
-rw-r--r--openjdk/sun/nio/ch/Net.java104
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
+ }
}