8233435: (dc) DatagramChannel should allow IPv6 socket join IPv4 multicast groups (macOS, win)
Reviewed-by: dfuchs
This commit is contained in:
parent
690b960c8f
commit
090dc51a4e
@ -239,6 +239,40 @@ class DatagramChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol family to specify to set/getSocketOption for the
|
||||
* given socket option.
|
||||
*/
|
||||
private ProtocolFamily familyFor(SocketOption<?> name) {
|
||||
assert Thread.holdsLock(stateLock);
|
||||
|
||||
// unspecified (most options)
|
||||
if (SocketOptionRegistry.findOption(name, Net.UNSPEC) != null)
|
||||
return Net.UNSPEC;
|
||||
|
||||
// IPv4 socket
|
||||
if (family == StandardProtocolFamily.INET)
|
||||
return StandardProtocolFamily.INET;
|
||||
|
||||
// IPv6 socket that is unbound
|
||||
if (localAddress == null)
|
||||
return StandardProtocolFamily.INET6;
|
||||
|
||||
// IPv6 socket bound to wildcard or IPv6 address
|
||||
InetAddress address = localAddress.getAddress();
|
||||
if (address.isAnyLocalAddress() || (address instanceof Inet6Address))
|
||||
return StandardProtocolFamily.INET6;
|
||||
|
||||
// IPv6 socket bound to IPv4 address
|
||||
if (Net.canUseIPv6OptionsWithIPv4LocalAddress()) {
|
||||
// IPV6_XXX options can be used
|
||||
return StandardProtocolFamily.INET6;
|
||||
} else {
|
||||
// IPV6_XXX options cannot be used
|
||||
return StandardProtocolFamily.INET;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DatagramChannel setOption(SocketOption<T> name, T value)
|
||||
throws IOException
|
||||
@ -252,14 +286,7 @@ class DatagramChannelImpl
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
|
||||
if (name == StandardSocketOptions.IP_TOS ||
|
||||
name == StandardSocketOptions.IP_MULTICAST_TTL ||
|
||||
name == StandardSocketOptions.IP_MULTICAST_LOOP)
|
||||
{
|
||||
// options are protocol dependent
|
||||
Net.setSocketOption(fd, family, name, value);
|
||||
return this;
|
||||
}
|
||||
ProtocolFamily family = familyFor(name);
|
||||
|
||||
if (name == StandardSocketOptions.IP_MULTICAST_IF) {
|
||||
NetworkInterface interf = (NetworkInterface)value;
|
||||
@ -285,7 +312,7 @@ class DatagramChannelImpl
|
||||
}
|
||||
|
||||
// remaining options don't need any special handling
|
||||
Net.setSocketOption(fd, Net.UNSPEC, name, value);
|
||||
Net.setSocketOption(fd, family, name, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@ -302,12 +329,7 @@ class DatagramChannelImpl
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
|
||||
if (name == StandardSocketOptions.IP_TOS ||
|
||||
name == StandardSocketOptions.IP_MULTICAST_TTL ||
|
||||
name == StandardSocketOptions.IP_MULTICAST_LOOP)
|
||||
{
|
||||
return (T) Net.getSocketOption(fd, family, name);
|
||||
}
|
||||
ProtocolFamily family = familyFor(name);
|
||||
|
||||
if (name == StandardSocketOptions.IP_MULTICAST_IF) {
|
||||
if (family == StandardProtocolFamily.INET) {
|
||||
@ -333,11 +355,11 @@ class DatagramChannelImpl
|
||||
}
|
||||
|
||||
if (name == StandardSocketOptions.SO_REUSEADDR && reuseAddressEmulated) {
|
||||
return (T)Boolean.valueOf(isReuseAddress);
|
||||
return (T) Boolean.valueOf(isReuseAddress);
|
||||
}
|
||||
|
||||
// no special handling
|
||||
return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
|
||||
return (T) Net.getSocketOption(fd, family, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,6 +121,14 @@ public class Net {
|
||||
return canJoin6WithIPv4Group0();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether IPV6_XXX socket options should be used on an IPv6 socket
|
||||
* that is bound to an IPv4 address.
|
||||
*/
|
||||
static boolean canUseIPv6OptionsWithIPv4LocalAddress() {
|
||||
return canUseIPv6OptionsWithIPv4LocalAddress0();
|
||||
}
|
||||
|
||||
public static InetSocketAddress checkAddress(SocketAddress sa) {
|
||||
if (sa == null)
|
||||
throw new NullPointerException();
|
||||
@ -434,6 +442,8 @@ public class Net {
|
||||
|
||||
private static native boolean canJoin6WithIPv4Group0();
|
||||
|
||||
private static native boolean canUseIPv6OptionsWithIPv4LocalAddress0();
|
||||
|
||||
static FileDescriptor socket(boolean stream) throws IOException {
|
||||
return socket(UNSPEC, stream);
|
||||
}
|
||||
|
@ -158,24 +158,34 @@ Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
|
||||
{
|
||||
#if defined(__APPLE__) || defined(_AIX)
|
||||
/* for now IPv6 sockets cannot join IPv4 multicast groups */
|
||||
return JNI_FALSE;
|
||||
#else
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(__solaris__)
|
||||
/* IPv6 sockets can join IPv4 multicast groups */
|
||||
return JNI_TRUE;
|
||||
#else
|
||||
/* IPv6 sockets cannot join IPv4 multicast groups */
|
||||
return JNI_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
|
||||
{
|
||||
#ifdef __solaris__
|
||||
#if defined(__APPLE__) || defined(__solaris__)
|
||||
/* IPV6_ADD_MEMBERSHIP can be used to join IPv4 multicast groups */
|
||||
return JNI_TRUE;
|
||||
#else
|
||||
/* IPV6_ADD_MEMBERSHIP cannot be used to join IPv4 multicast groups */
|
||||
return JNI_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_Net_canUseIPv6OptionsWithIPv4LocalAddress0(JNIEnv* env, jclass cl)
|
||||
{
|
||||
/* IPV6_XXX socket options can be used on IPv6 sockets bound to IPv4 address */
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
|
||||
jboolean stream, jboolean reuse, jboolean ignored)
|
||||
|
@ -127,12 +127,21 @@ Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
|
||||
{
|
||||
return JNI_FALSE;
|
||||
/* IPv6 sockets can join IPv4 multicast groups */
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
|
||||
{
|
||||
/* IPV6_ADD_MEMBERSHIP cannot be used to join IPv4 multicast groups */
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_Net_canUseIPv6OptionsWithIPv4LocalAddress0(JNIEnv* env, jclass cl)
|
||||
{
|
||||
/* IPV6_XXX socket options cannot be used on IPv6 sockets bound to IPv4 address */
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
@ -279,7 +288,7 @@ Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
|
||||
SOCKETADDRESS sa;
|
||||
int sa_len = sizeof(sa);
|
||||
|
||||
if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
|
||||
if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) == SOCKET_ERROR) {
|
||||
int error = WSAGetLastError();
|
||||
if (error == WSAEINVAL) {
|
||||
return 0;
|
||||
@ -297,7 +306,7 @@ Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
|
||||
int sa_len = sizeof(sa);
|
||||
int port;
|
||||
|
||||
if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
|
||||
if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
|
||||
return NULL;
|
||||
}
|
||||
@ -310,7 +319,7 @@ Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo)
|
||||
SOCKETADDRESS sa;
|
||||
int sa_len = sizeof(sa);
|
||||
|
||||
if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
|
||||
if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) == SOCKET_ERROR) {
|
||||
int error = WSAGetLastError();
|
||||
if (error == WSAEINVAL) {
|
||||
return 0;
|
||||
@ -328,7 +337,7 @@ Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
|
||||
int sa_len = sizeof(sa);
|
||||
int port;
|
||||
|
||||
if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
|
||||
if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
|
||||
return NULL;
|
||||
}
|
||||
@ -366,7 +375,7 @@ Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
|
||||
} else {
|
||||
n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
|
||||
}
|
||||
if (n < 0) {
|
||||
if (n == SOCKET_ERROR) {
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
return IOS_THROWN;
|
||||
}
|
||||
@ -410,7 +419,7 @@ Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
|
||||
} else {
|
||||
n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
|
||||
}
|
||||
if (n < 0)
|
||||
if (n == SOCKET_ERROR)
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
}
|
||||
|
||||
@ -439,7 +448,7 @@ Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobjec
|
||||
}
|
||||
|
||||
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
|
||||
if (n < 0) {
|
||||
if (n == SOCKET_ERROR) {
|
||||
if (join && (WSAGetLastError() == WSAENOPROTOOPT))
|
||||
return IOS_UNAVAILABLE;
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
@ -461,7 +470,7 @@ Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, j
|
||||
|
||||
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
|
||||
(void*)&mreq_source, sizeof(mreq_source));
|
||||
if (n < 0) {
|
||||
if (n == SOCKET_ERROR) {
|
||||
if (block && (WSAGetLastError() == WSAENOPROTOOPT))
|
||||
return IOS_UNAVAILABLE;
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
@ -516,8 +525,8 @@ Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobjec
|
||||
n = setGroupSourceReqOption(env, fdo, opt, group, index, source);
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
handleSocketError(env, errno);
|
||||
if (n == SOCKET_ERROR) {
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -528,8 +537,8 @@ Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, j
|
||||
{
|
||||
int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
|
||||
int n = setGroupSourceReqOption(env, fdo, opt, group, index, source);
|
||||
if (n < 0) {
|
||||
handleSocketError(env, errno);
|
||||
if (n == SOCKET_ERROR) {
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -545,7 +554,7 @@ Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint i
|
||||
|
||||
n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
|
||||
(void*)&(in.s_addr), arglen);
|
||||
if (n < 0) {
|
||||
if (n == SOCKET_ERROR) {
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
}
|
||||
}
|
||||
@ -558,7 +567,7 @@ Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
|
||||
int n;
|
||||
|
||||
n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
|
||||
if (n < 0) {
|
||||
if (n == SOCKET_ERROR) {
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
return IOS_THROWN;
|
||||
}
|
||||
@ -568,27 +577,27 @@ Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
|
||||
{
|
||||
int value = (jint)index;
|
||||
DWORD value = (jint)index;
|
||||
int arglen = sizeof(value);
|
||||
int n;
|
||||
|
||||
n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
||||
(void*)&(index), arglen);
|
||||
if (n < 0) {
|
||||
handleSocketError(env, errno);
|
||||
if (n == SOCKET_ERROR) {
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
|
||||
{
|
||||
int index;
|
||||
DWORD index;
|
||||
int arglen = sizeof(index);
|
||||
int n;
|
||||
|
||||
n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
|
||||
if (n < 0) {
|
||||
handleSocketError(env, errno);
|
||||
if (n == SOCKET_ERROR) {
|
||||
handleSocketError(env, WSAGetLastError());
|
||||
return -1;
|
||||
}
|
||||
return (jint)index;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2019, 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
|
||||
@ -22,11 +22,12 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4527345 7026376 6633549
|
||||
* @bug 4527345 7026376 6633549 8233435
|
||||
* @summary Unit test for DatagramChannel's multicast support
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* jdk.test.lib.net.IPSupport
|
||||
* MulticastSendReceiveTests
|
||||
* @run main MulticastSendReceiveTests
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true MulticastSendReceiveTests
|
||||
@ -41,6 +42,7 @@ import java.util.*;
|
||||
import java.io.IOException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
@ -242,23 +244,37 @@ public class MulticastSendReceiveTests {
|
||||
public static void main(String[] args) throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
|
||||
// IPv4 and IPv6 interfaces that support multicasting
|
||||
NetworkConfiguration config = NetworkConfiguration.probe();
|
||||
List<NetworkInterface> ip4MulticastInterfaces = config.ip4MulticastInterfaces()
|
||||
.collect(Collectors.toList());
|
||||
List<NetworkInterface> ip6MulticastInterfaces = config.ip6MulticastInterfaces()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// multicast groups used for the test
|
||||
InetAddress ip4Group = InetAddress.getByName("225.4.5.6");
|
||||
InetAddress ip6Group = InetAddress.getByName("ff02::a");
|
||||
for (NetworkInterface nif: config.ip4MulticastInterfaces()
|
||||
.collect(Collectors.toList())) {
|
||||
|
||||
// Platforms that allow dual sockets join IPv4 multicast groups
|
||||
boolean canIPv6JoinIPv4Group =
|
||||
Platform.isLinux() ||
|
||||
Platform.isOSX() ||
|
||||
Platform.isSolaris() ||
|
||||
Platform.isWindows();
|
||||
|
||||
for (NetworkInterface nif : ip4MulticastInterfaces) {
|
||||
InetAddress source = config.ip4Addresses(nif).iterator().next();
|
||||
test(INET, nif, ip4Group, source);
|
||||
test(UNSPEC, nif, ip4Group, source);
|
||||
test(INET, nif, ip4Group, source);
|
||||
if (IPSupport.hasIPv6() && canIPv6JoinIPv4Group) {
|
||||
test(INET6, nif, ip4Group, source);
|
||||
}
|
||||
}
|
||||
|
||||
for (NetworkInterface nif: config.ip6MulticastInterfaces()
|
||||
.collect(Collectors.toList())) {
|
||||
for (NetworkInterface nif : ip6MulticastInterfaces) {
|
||||
InetAddress source = config.ip6Addresses(nif).iterator().next();
|
||||
test(INET6, nif, ip6Group, source);
|
||||
test(UNSPEC, nif, ip6Group, source);
|
||||
test(INET6, nif, ip6Group, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2019, 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
|
||||
@ -22,10 +22,15 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4640544 8044773
|
||||
* @bug 4640544 8044773 8233435
|
||||
* @summary Unit test for setOption/getOption/options methods
|
||||
* @requires !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.net.IPSupport
|
||||
* jdk.test.lib.NetworkConfiguration
|
||||
* SocketOptionTests
|
||||
* @run main SocketOptionTests
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true SocketOptionTests
|
||||
* @run main/othervm --limit-modules=java.base SocketOptionTests
|
||||
*/
|
||||
|
||||
@ -34,23 +39,61 @@ import java.nio.channels.*;
|
||||
import java.net.*;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import static java.net.StandardProtocolFamily.*;
|
||||
import static java.net.StandardSocketOptions.*;
|
||||
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
public class SocketOptionTests {
|
||||
|
||||
static <T> void checkOption(DatagramChannel dc,
|
||||
SocketOption<T> name,
|
||||
T expectedValue)
|
||||
throws IOException
|
||||
{
|
||||
T value = dc.getOption(name);
|
||||
if (!value.equals(expectedValue))
|
||||
throw new RuntimeException("value not as expected");
|
||||
public static void main(String[] args) throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
|
||||
NetworkConfiguration config = NetworkConfiguration.probe();
|
||||
InetAddress ip4Address = config.ip4Addresses().findAny().orElse(null);
|
||||
InetAddress ip6Address = config.ip6Addresses().findAny().orElse(null);
|
||||
|
||||
System.out.println("[UNSPEC, bound to wildcard address]");
|
||||
try (DatagramChannel dc = DatagramChannel.open()) {
|
||||
test(dc, new InetSocketAddress(0));
|
||||
}
|
||||
|
||||
if (IPSupport.hasIPv4()) {
|
||||
System.out.println("[INET, bound to wildcard address]");
|
||||
try (DatagramChannel dc = DatagramChannel.open(INET)) {
|
||||
test(dc, new InetSocketAddress(0));
|
||||
}
|
||||
System.out.println("[INET, bound to IPv4 address]");
|
||||
try (DatagramChannel dc = DatagramChannel.open(INET)) {
|
||||
test(dc, new InetSocketAddress(ip4Address, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (IPSupport.hasIPv6()) {
|
||||
System.out.println("[INET6, bound to wildcard address]");
|
||||
try (DatagramChannel dc = DatagramChannel.open(INET6)) {
|
||||
test(dc, new InetSocketAddress(0));
|
||||
}
|
||||
System.out.println("[INET6, bound to IPv6 address]");
|
||||
try (DatagramChannel dc = DatagramChannel.open(INET6)) {
|
||||
test(dc, new InetSocketAddress(ip6Address, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (IPSupport.hasIPv4() && IPSupport.hasIPv6()) {
|
||||
System.out.println("[UNSPEC, bound to IPv4 address]");
|
||||
try (DatagramChannel dc = DatagramChannel.open()) {
|
||||
test(dc, new InetSocketAddress(ip4Address, 0));
|
||||
}
|
||||
System.out.println("[INET6, bound to IPv4 address]");
|
||||
try (DatagramChannel dc = DatagramChannel.open(INET6)) {
|
||||
test(dc, new InetSocketAddress(ip4Address, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
DatagramChannel dc = DatagramChannel.open();
|
||||
|
||||
static void test(DatagramChannel dc, SocketAddress localAddress) throws IOException {
|
||||
// check supported options
|
||||
Set<SocketOption<?>> options = dc.supportedOptions();
|
||||
boolean reuseport = options.contains(SO_REUSEPORT);
|
||||
@ -101,7 +144,7 @@ public class SocketOptionTests {
|
||||
checkOption(dc, SO_REUSEPORT, false);
|
||||
}
|
||||
// bind socket
|
||||
dc.bind(new InetSocketAddress(0));
|
||||
dc.bind(localAddress);
|
||||
|
||||
// allow to change when bound
|
||||
dc.setOption(SO_BROADCAST, true);
|
||||
@ -116,7 +159,6 @@ public class SocketOptionTests {
|
||||
dc.setOption(IP_MULTICAST_LOOP, true);
|
||||
checkOption(dc, IP_MULTICAST_LOOP, true);
|
||||
|
||||
|
||||
// NullPointerException
|
||||
try {
|
||||
dc.setOption(null, "value");
|
||||
@ -137,4 +179,14 @@ public class SocketOptionTests {
|
||||
} catch (ClosedChannelException x) {
|
||||
}
|
||||
}
|
||||
|
||||
static <T> void checkOption(DatagramChannel dc,
|
||||
SocketOption<T> name,
|
||||
T expectedValue)
|
||||
throws IOException
|
||||
{
|
||||
T value = dc.getOption(name);
|
||||
if (!value.equals(expectedValue))
|
||||
throw new RuntimeException("value not as expected");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user