Path: blob/master/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java
41159 views
/*1* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.net.ext;2627import java.io.FileDescriptor;28import java.net.SocketException;29import java.net.SocketOption;30import java.util.Collections;31import java.util.HashSet;32import java.util.Set;3334/**35* Defines the infrastructure to support extended socket options, beyond those36* defined in {@link java.net.StandardSocketOptions}.37*38* Extended socket options are accessed through the jdk.net API, which is in39* the jdk.net module.40*/41public abstract class ExtendedSocketOptions {4243public static final short SOCK_STREAM = 1;44public static final short SOCK_DGRAM = 2;4546private final Set<SocketOption<?>> options;47private final Set<SocketOption<?>> datagramOptions;48private final Set<SocketOption<?>> clientStreamOptions;49private final Set<SocketOption<?>> serverStreamOptions;50private final Set<SocketOption<?>> unixDomainClientOptions;5152/** Tells whether or not the option is supported. */53public final boolean isOptionSupported(SocketOption<?> option) {54return options().contains(option);55}5657/** Return the, possibly empty, set of extended socket options available. */58public final Set<SocketOption<?>> options() { return options; }5960/**61* Returns the (possibly empty) set of extended socket options for62* stream-oriented listening sockets.63*/64public static Set<SocketOption<?>> serverSocketOptions() {65return getInstance().options0(SOCK_STREAM, true);66}6768/**69* Returns the (possibly empty) set of extended socket options for70* stream-oriented connecting sockets.71*/72public static Set<SocketOption<?>> clientSocketOptions() {73return getInstance().options0(SOCK_STREAM, false);74}7576/**77* Return the, possibly empty, set of extended socket options available for78* Unix domain client sockets. Note, there are no extended79* Unix domain server options.80*/81private final Set<SocketOption<?>> unixDomainClientOptions() {82return unixDomainClientOptions;83}8485public static Set<SocketOption<?>> unixDomainSocketOptions() {86return getInstance().unixDomainClientOptions();87}8889/**90* Returns the (possibly empty) set of extended socket options for91* datagram-oriented sockets.92*/93public static Set<SocketOption<?>> datagramSocketOptions() {94return getInstance().options0(SOCK_DGRAM, false);95}9697private static boolean isDatagramOption(SocketOption<?> option) {98if (option.name().startsWith("TCP_") || isUnixDomainOption(option)) {99return false;100} else {101return true;102}103}104105private static boolean isUnixDomainOption(SocketOption<?> option) {106return option.name().equals("SO_PEERCRED");107}108109private static boolean isStreamOption(SocketOption<?> option, boolean server) {110if (option.name().startsWith("UDP_") || isUnixDomainOption(option)) {111return false;112} else {113return true;114}115}116117private Set<SocketOption<?>> options0(short type, boolean server) {118switch (type) {119case SOCK_DGRAM:120return datagramOptions;121case SOCK_STREAM:122if (server) {123return serverStreamOptions;124} else {125return clientStreamOptions;126}127default:128//this will never happen129throw new IllegalArgumentException("Invalid socket option type");130}131}132133/** Sets the value of a socket option, for the given socket. */134public abstract void setOption(FileDescriptor fd, SocketOption<?> option, Object value)135throws SocketException;136137/** Returns the value of a socket option, for the given socket. */138public abstract Object getOption(FileDescriptor fd, SocketOption<?> option)139throws SocketException;140141protected ExtendedSocketOptions(Set<SocketOption<?>> options) {142this.options = options;143var datagramOptions = new HashSet<SocketOption<?>>();144var serverStreamOptions = new HashSet<SocketOption<?>>();145var clientStreamOptions = new HashSet<SocketOption<?>>();146var unixDomainClientOptions = new HashSet<SocketOption<?>>();147for (var option : options) {148if (isDatagramOption(option)) {149datagramOptions.add(option);150}151if (isStreamOption(option, true)) {152serverStreamOptions.add(option);153}154if (isStreamOption(option, false)) {155clientStreamOptions.add(option);156}157if (isUnixDomainOption(option)) {158unixDomainClientOptions.add(option);159}160}161this.datagramOptions = Set.copyOf(datagramOptions);162this.serverStreamOptions = Set.copyOf(serverStreamOptions);163this.clientStreamOptions = Set.copyOf(clientStreamOptions);164this.unixDomainClientOptions = Set.copyOf(unixDomainClientOptions);165}166167private static volatile ExtendedSocketOptions instance;168169public static ExtendedSocketOptions getInstance() {170ExtendedSocketOptions ext = instance;171if (ext != null) {172return ext;173}174try {175// If the class is present, it will be initialized which176// triggers registration of the extended socket options.177Class<?> c = Class.forName("jdk.net.ExtendedSocketOptions");178ext = instance;179} catch (ClassNotFoundException e) {180synchronized (ExtendedSocketOptions.class) {181ext = instance;182if (ext != null) {183return ext;184}185// the jdk.net module is not present => no extended socket options186ext = instance = new NoExtendedSocketOptions();187}188}189return ext;190}191192/** Registers support for extended socket options. Invoked by the jdk.net module. */193public static synchronized void register(ExtendedSocketOptions extOptions) {194if (instance != null)195throw new InternalError("Attempting to reregister extended options");196197instance = extOptions;198}199200static final class NoExtendedSocketOptions extends ExtendedSocketOptions {201202NoExtendedSocketOptions() {203super(Collections.<SocketOption<?>>emptySet());204}205206@Override207public void setOption(FileDescriptor fd, SocketOption<?> option, Object value)208throws SocketException209{210throw new UnsupportedOperationException(211"no extended options: " + option.name());212}213214@Override215public Object getOption(FileDescriptor fd, SocketOption<?> option)216throws SocketException217{218throw new UnsupportedOperationException(219"no extended options: " + option.name());220}221}222}223224225