8217451: ExtendedSocketOptions should encapsulate support for SO_FLOW_SLA

Reviewed-by: michaelm, chegar
This commit is contained in:
Alan Bateman 2019-01-22 12:32:19 +00:00
parent 911c7ff446
commit bb1e1c7120
9 changed files with 79 additions and 66 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -54,21 +54,53 @@ public abstract class ExtendedSocketOptions {
/** Return the, possibly empty, set of extended socket options available. */ /** Return the, possibly empty, set of extended socket options available. */
public final Set<SocketOption<?>> options() { return options; } public final Set<SocketOption<?>> options() { return options; }
public static final Set<SocketOption<?>> options(short type) { /**
return getInstance().options0(type); * Returns the (possibly empty) set of extended socket options for
* stream-oriented listening sockets.
*/
public static Set<SocketOption<?>> serverSocketOptions() {
return getInstance().options0(SOCK_STREAM, true);
} }
private Set<SocketOption<?>> options0(short type) { /**
Set<SocketOption<?>> extOptions = null; * Returns the (possibly empty) set of extended socket options for
* stream-oriented connecting sockets.
*/
public static Set<SocketOption<?>> clientSocketOptions() {
return getInstance().options0(SOCK_STREAM, false);
}
/**
* Returns the (possibly empty) set of extended socket options for
* datagram-oriented sockets.
*/
public static Set<SocketOption<?>> datagramSocketOptions() {
return getInstance().options0(SOCK_DGRAM, false);
}
private boolean isDatagramOption(SocketOption<?> option) {
return !option.name().startsWith("TCP_");
}
private boolean isStreamOption(SocketOption<?> option, boolean server) {
if (server && "SO_FLOW_SLA".equals(option.name())) {
return false;
} else {
return !option.name().startsWith("UDP_");
}
}
private Set<SocketOption<?>> options0(short type, boolean server) {
Set<SocketOption<?>> extOptions;
switch (type) { switch (type) {
case SOCK_DGRAM: case SOCK_DGRAM:
extOptions = options.stream() extOptions = options.stream()
.filter((option) -> !option.name().startsWith("TCP_")) .filter(option -> isDatagramOption(option))
.collect(Collectors.toUnmodifiableSet()); .collect(Collectors.toUnmodifiableSet());
break; break;
case SOCK_STREAM: case SOCK_STREAM:
extOptions = options.stream() extOptions = options.stream()
.filter((option) -> !option.name().startsWith("UDP_")) .filter(option -> isStreamOption(option, server))
.collect(Collectors.toUnmodifiableSet()); .collect(Collectors.toUnmodifiableSet());
break; break;
default: default:

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -40,7 +40,6 @@ import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import sun.net.NetHooks; import sun.net.NetHooks;
import sun.net.ext.ExtendedSocketOptions; import sun.net.ext.ExtendedSocketOptions;
import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM;
/** /**
* Base implementation of AsynchronousServerSocketChannel. * Base implementation of AsynchronousServerSocketChannel.
@ -236,7 +235,7 @@ abstract class AsynchronousServerSocketChannelImpl
if (Net.isReusePortAvailable()) { if (Net.isReusePortAvailable()) {
set.add(StandardSocketOptions.SO_REUSEPORT); set.add(StandardSocketOptions.SO_REUSEPORT);
} }
set.addAll(ExtendedSocketOptions.options(SOCK_STREAM)); set.addAll(ExtendedSocketOptions.serverSocketOptions());
return Collections.unmodifiableSet(set); return Collections.unmodifiableSet(set);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -40,7 +40,6 @@ import java.util.concurrent.*;
import java.util.concurrent.locks.*; import java.util.concurrent.locks.*;
import sun.net.NetHooks; import sun.net.NetHooks;
import sun.net.ext.ExtendedSocketOptions; import sun.net.ext.ExtendedSocketOptions;
import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM;
/** /**
* Base implementation of AsynchronousSocketChannel * Base implementation of AsynchronousSocketChannel
@ -513,7 +512,7 @@ abstract class AsynchronousSocketChannelImpl
set.add(StandardSocketOptions.SO_REUSEPORT); set.add(StandardSocketOptions.SO_REUSEPORT);
} }
set.add(StandardSocketOptions.TCP_NODELAY); set.add(StandardSocketOptions.TCP_NODELAY);
set.addAll(ExtendedSocketOptions.options(SOCK_STREAM)); set.addAll(ExtendedSocketOptions.clientSocketOptions());
return Collections.unmodifiableSet(set); return Collections.unmodifiableSet(set);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -57,7 +57,6 @@ import java.util.concurrent.locks.ReentrantLock;
import sun.net.ResourceManager; import sun.net.ResourceManager;
import sun.net.ext.ExtendedSocketOptions; import sun.net.ext.ExtendedSocketOptions;
import static sun.net.ext.ExtendedSocketOptions.SOCK_DGRAM;
/** /**
* An implementation of DatagramChannels. * An implementation of DatagramChannels.
@ -335,7 +334,7 @@ class DatagramChannelImpl
set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_IF);
set.add(StandardSocketOptions.IP_MULTICAST_TTL); set.add(StandardSocketOptions.IP_MULTICAST_TTL);
set.add(StandardSocketOptions.IP_MULTICAST_LOOP); set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
set.addAll(ExtendedSocketOptions.options(SOCK_DGRAM)); set.addAll(ExtendedSocketOptions.datagramSocketOptions());
return Collections.unmodifiableSet(set); return Collections.unmodifiableSet(set);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,11 +28,9 @@ package sun.nio.ch;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.ProtocolFamily;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.net.SocketOption; import java.net.SocketOption;
import java.net.StandardProtocolFamily;
import java.net.StandardSocketOptions; import java.net.StandardSocketOptions;
import java.nio.channels.AlreadyBoundException; import java.nio.channels.AlreadyBoundException;
import java.nio.channels.AsynchronousCloseException; import java.nio.channels.AsynchronousCloseException;
@ -50,7 +48,6 @@ import java.util.concurrent.locks.ReentrantLock;
import sun.net.NetHooks; import sun.net.NetHooks;
import sun.net.ext.ExtendedSocketOptions; import sun.net.ext.ExtendedSocketOptions;
import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM;
/** /**
* An implementation of ServerSocketChannels * An implementation of ServerSocketChannels
@ -193,7 +190,7 @@ class ServerSocketChannelImpl
if (Net.isReusePortAvailable()) { if (Net.isReusePortAvailable()) {
set.add(StandardSocketOptions.SO_REUSEPORT); set.add(StandardSocketOptions.SO_REUSEPORT);
} }
set.addAll(ExtendedSocketOptions.options(SOCK_STREAM)); set.addAll(ExtendedSocketOptions.serverSocketOptions());
return Collections.unmodifiableSet(set); return Collections.unmodifiableSet(set);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -55,7 +55,6 @@ import java.util.concurrent.locks.ReentrantLock;
import sun.net.NetHooks; import sun.net.NetHooks;
import sun.net.ext.ExtendedSocketOptions; import sun.net.ext.ExtendedSocketOptions;
import sun.net.util.SocketExceptions; import sun.net.util.SocketExceptions;
import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM;
/** /**
* An implementation of SocketChannels * An implementation of SocketChannels
@ -282,7 +281,7 @@ class SocketChannelImpl
// additional options required by socket adaptor // additional options required by socket adaptor
set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.IP_TOS);
set.add(ExtendedSocketOption.SO_OOBINLINE); set.add(ExtendedSocketOption.SO_OOBINLINE);
set.addAll(ExtendedSocketOptions.options(SOCK_STREAM)); set.addAll(ExtendedSocketOptions.clientSocketOptions());
return Collections.unmodifiableSet(set); return Collections.unmodifiableSet(set);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, 2018, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,7 +28,6 @@ import java.io.IOException;
import java.util.Set; import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import sun.net.ext.ExtendedSocketOptions; import sun.net.ext.ExtendedSocketOptions;
import static sun.net.ext.ExtendedSocketOptions.SOCK_DGRAM;
/* /*
* On Unix systems we simply delegate to native methods. * On Unix systems we simply delegate to native methods.
@ -78,7 +77,7 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
protected Set<SocketOption<?>> supportedOptions() { protected Set<SocketOption<?>> supportedOptions() {
HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions()); HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions());
options.addAll(ExtendedSocketOptions.options(SOCK_DGRAM)); options.addAll(ExtendedSocketOptions.datagramSocketOptions());
return options; return options;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, 2018, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -29,7 +29,6 @@ import java.io.FileDescriptor;
import java.util.Set; import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import sun.net.ext.ExtendedSocketOptions; import sun.net.ext.ExtendedSocketOptions;
import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM;
/* /*
* On Unix systems we simply delegate to native methods. * On Unix systems we simply delegate to native methods.
@ -91,25 +90,14 @@ class PlainSocketImpl extends AbstractPlainSocketImpl
protected Set<SocketOption<?>> supportedOptions() { protected Set<SocketOption<?>> supportedOptions() {
HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions()); HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions());
addExtSocketOptions(ExtendedSocketOptions.options(SOCK_STREAM), options); if (getServerSocket() != null) {
options.addAll(ExtendedSocketOptions.serverSocketOptions());
} else {
options.addAll(ExtendedSocketOptions.clientSocketOptions());
}
return options; return options;
} }
private void addExtSocketOptions(Set<SocketOption<?>> extOptions,
Set<SocketOption<?>> options) {
extOptions.forEach((option) -> {
if (option.name().equals("SO_FLOW_SLA")) {
// SO_FLOW_SLA is Solaris specific option which is not applicable
// for ServerSockets.
// getSocket() will always return null for server socket
if (getSocket() != null) {
options.add(option);
}
} else {
options.add(option);
}
});
}
protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { protected void socketSetOption(int opt, boolean b, Object val) throws SocketException {
if (opt == SocketOptions.SO_REUSEPORT && if (opt == SocketOptions.SO_REUSEPORT &&
!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, 2018, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -32,14 +32,15 @@
* @run main/othervm --limit-modules=java.base SocketOptionTests * @run main/othervm --limit-modules=java.base SocketOptionTests
*/ */
import java.nio.channels.*;
import java.net.*;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.net.InetSocketAddress;
import java.net.SocketOption;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SocketChannel;
import java.util.Set;
import sun.net.ext.ExtendedSocketOptions;
import static java.net.StandardSocketOptions.*; import static java.net.StandardSocketOptions.*;
import static jdk.net.ExtendedSocketOptions.*; import static jdk.net.ExtendedSocketOptions.*;
import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM;
import sun.net.ext.ExtendedSocketOptions;
public class SocketOptionTests { public class SocketOptionTests {
@ -52,26 +53,26 @@ public class SocketOptionTests {
} }
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
SocketChannel sc = SocketChannel.open(); try (var channel = SocketChannel.open()) {
test(channel);
}
}
// check supported options static void test(SocketChannel sc) throws IOException {
Set<SocketOption<?>> options = sc.supportedOptions(); Set<SocketOption<?>> extendedOptions = ExtendedSocketOptions.clientSocketOptions();
Set<SocketOption<?>> keepAliveOptions = Set.of(TCP_KEEPCOUNT, TCP_KEEPIDLE, TCP_KEEPINTERVAL);
List<? extends SocketOption> extOptions = List.of(TCP_KEEPCOUNT, boolean keepAliveOptionsSupported = extendedOptions.containsAll(keepAliveOptions);
TCP_KEEPIDLE, TCP_KEEPINTERVAL); Set<SocketOption<?>> expected;
List<? extends SocketOption> expected; if (keepAliveOptionsSupported) {
boolean keepAliveOptsupported; expected = Set.of(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE,
if (keepAliveOptsupported=ExtendedSocketOptions.options(SOCK_STREAM)
.containsAll(extOptions)) {
expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE,
SO_REUSEADDR, SO_LINGER, TCP_NODELAY, TCP_KEEPCOUNT, SO_REUSEADDR, SO_LINGER, TCP_NODELAY, TCP_KEEPCOUNT,
TCP_KEEPIDLE, TCP_KEEPINTERVAL); TCP_KEEPIDLE, TCP_KEEPINTERVAL);
} else { } else {
expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE, expected = Set.of(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE,
SO_REUSEADDR, SO_LINGER, TCP_NODELAY); SO_REUSEADDR, SO_LINGER, TCP_NODELAY);
} }
for (SocketOption opt: expected) { for (SocketOption opt: expected) {
if (!options.contains(opt)) if (!sc.supportedOptions().contains(opt))
throw new RuntimeException(opt.name() + " should be supported"); throw new RuntimeException(opt.name() + " should be supported");
} }
@ -133,7 +134,7 @@ public class SocketOptionTests {
throw new RuntimeException("expected linger to be disabled"); throw new RuntimeException("expected linger to be disabled");
sc.setOption(TCP_NODELAY, true); // can't check sc.setOption(TCP_NODELAY, true); // can't check
sc.setOption(TCP_NODELAY, false); // can't check sc.setOption(TCP_NODELAY, false); // can't check
if (keepAliveOptsupported) { if (keepAliveOptionsSupported) {
sc.setOption(TCP_KEEPIDLE, 1234); sc.setOption(TCP_KEEPIDLE, 1234);
checkOption(sc, TCP_KEEPIDLE, 1234); checkOption(sc, TCP_KEEPIDLE, 1234);
sc.setOption(TCP_KEEPINTERVAL, 123); sc.setOption(TCP_KEEPINTERVAL, 123);
@ -161,4 +162,4 @@ public class SocketOptionTests {
} catch (ClosedChannelException x) { } catch (ClosedChannelException x) {
} }
} }
} }