8044773: Refactor jdk.net API so that it can be moved out of the base module
Reviewed-by: alanb, erikj, mchung
This commit is contained in:
parent
f340281533
commit
07cef26155
51
jdk/make/lib/Lib-jdk.net.gmk
Normal file
51
jdk/make/lib/Lib-jdk.net.gmk
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2016, 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
|
||||||
|
# under the terms of the GNU General Public License version 2 only, as
|
||||||
|
# published by the Free Software Foundation. Oracle designates this
|
||||||
|
# particular file as subject to the "Classpath" exception as provided
|
||||||
|
# by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
#
|
||||||
|
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
# accompanied this code).
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License version
|
||||||
|
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
# or visit www.oracle.com if you need additional information or have any
|
||||||
|
# questions.
|
||||||
|
#
|
||||||
|
|
||||||
|
include LibCommon.gmk
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
ifeq ($(OPENJDK_TARGET_OS), solaris)
|
||||||
|
|
||||||
|
$(eval $(call SetupNativeCompilation, BUILD_LIBEXTNET, \
|
||||||
|
LIBRARY := extnet, \
|
||||||
|
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
|
||||||
|
SRC := $(JDK_TOPDIR)/src/jdk.net/solaris/native/libextnet, \
|
||||||
|
OPTIMIZATION := LOW, \
|
||||||
|
CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.net, \
|
||||||
|
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libextnet/mapfile-vers, \
|
||||||
|
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||||
|
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||||
|
LIBS := -lsocket -lc -ljava, \
|
||||||
|
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libextnet, \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(BUILD_LIBEXTNET): $(call FindLib, java.base, java)
|
||||||
|
|
||||||
|
TARGETS += $(BUILD_LIBEXTNET)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
34
jdk/make/mapfiles/libextnet/mapfile-vers
Normal file
34
jdk/make/mapfiles/libextnet/mapfile-vers
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2016, 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
|
||||||
|
# under the terms of the GNU General Public License version 2 only, as
|
||||||
|
# published by the Free Software Foundation. Oracle designates this
|
||||||
|
# particular file as subject to the "Classpath" exception as provided
|
||||||
|
# by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
#
|
||||||
|
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
# accompanied this code).
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License version
|
||||||
|
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
# or visit www.oracle.com if you need additional information or have any
|
||||||
|
# questions.
|
||||||
|
#
|
||||||
|
|
||||||
|
SUNWprivate_1.1 {
|
||||||
|
global:
|
||||||
|
Java_jdk_net_SolarisSocketOptions_init;
|
||||||
|
Java_jdk_net_SolarisSocketOptions_setFlowOption;
|
||||||
|
Java_jdk_net_SolarisSocketOptions_getFlowOption;
|
||||||
|
Java_jdk_net_SolarisSocketOptions_flowSupported;
|
||||||
|
local:
|
||||||
|
*;
|
||||||
|
};
|
@ -98,10 +98,6 @@ SUNWprivate_1.1 {
|
|||||||
Java_sun_net_sdp_SdpSupport_create0;
|
Java_sun_net_sdp_SdpSupport_create0;
|
||||||
Java_sun_net_spi_DefaultProxySelector_init;
|
Java_sun_net_spi_DefaultProxySelector_init;
|
||||||
Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
|
Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
|
||||||
Java_sun_net_ExtendedOptionsImpl_init;
|
|
||||||
Java_sun_net_ExtendedOptionsImpl_setFlowOption;
|
|
||||||
Java_sun_net_ExtendedOptionsImpl_getFlowOption;
|
|
||||||
Java_sun_net_ExtendedOptionsImpl_flowSupported;
|
|
||||||
NET_AllocSockaddr;
|
NET_AllocSockaddr;
|
||||||
NET_SockaddrToInetAddress;
|
NET_SockaddrToInetAddress;
|
||||||
NET_SockaddrEqualsInetAddress;
|
NET_SockaddrEqualsInetAddress;
|
||||||
|
@ -52,7 +52,7 @@ public class GenModuleInfoSource {
|
|||||||
"Usage: GenModuleInfoSource [option] -o <output file> <module-info-java>\n" +
|
"Usage: GenModuleInfoSource [option] -o <output file> <module-info-java>\n" +
|
||||||
"Options are:\n" +
|
"Options are:\n" +
|
||||||
" -exports <package-name>\n" +
|
" -exports <package-name>\n" +
|
||||||
" -exports <package-name>/<module-name>\n" +
|
" -exports <package-name>[/<module-name>]\n" +
|
||||||
" -uses <service>\n" +
|
" -uses <service>\n" +
|
||||||
" -provides <service>/<provider-impl-classname>\n";
|
" -provides <service>/<provider-impl-classname>\n";
|
||||||
|
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014, 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
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jdk.net;
|
|
||||||
|
|
||||||
import java.net.SocketOption;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines extended socket options, beyond those defined in
|
|
||||||
* {@link java.net.StandardSocketOptions}. These options may be platform
|
|
||||||
* specific.
|
|
||||||
*
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public final class ExtendedSocketOptions {
|
|
||||||
|
|
||||||
private static class ExtSocketOption<T> implements SocketOption<T> {
|
|
||||||
private final String name;
|
|
||||||
private final Class<T> type;
|
|
||||||
ExtSocketOption(String name, Class<T> type) {
|
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
@Override public String name() { return name; }
|
|
||||||
@Override public Class<T> type() { return type; }
|
|
||||||
@Override public String toString() { return name; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private ExtendedSocketOptions() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service level properties. When a security manager is installed,
|
|
||||||
* setting or getting this option requires a {@link NetworkPermission}
|
|
||||||
* {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"}
|
|
||||||
* respectively.
|
|
||||||
*/
|
|
||||||
public static final SocketOption<SocketFlow> SO_FLOW_SLA = new
|
|
||||||
ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class);
|
|
||||||
}
|
|
@ -83,8 +83,6 @@ module java.base {
|
|||||||
|
|
||||||
// see JDK-8144062
|
// see JDK-8144062
|
||||||
exports jdk;
|
exports jdk;
|
||||||
// see JDK-8044773
|
|
||||||
exports jdk.net;
|
|
||||||
|
|
||||||
|
|
||||||
// the service types defined by the APIs in this module
|
// the service types defined by the APIs in this module
|
||||||
@ -194,6 +192,8 @@ module java.base {
|
|||||||
jdk.jvmstat;
|
jdk.jvmstat;
|
||||||
exports sun.net to
|
exports sun.net to
|
||||||
java.httpclient;
|
java.httpclient;
|
||||||
|
exports sun.net.ext to
|
||||||
|
jdk.net;
|
||||||
exports sun.net.dns to
|
exports sun.net.dns to
|
||||||
java.security.jgss,
|
java.security.jgss,
|
||||||
jdk.naming.dns;
|
jdk.naming.dns;
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014, 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
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.net;
|
|
||||||
|
|
||||||
import java.net.*;
|
|
||||||
import jdk.net.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.FileDescriptor;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.security.AccessController;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains the native implementation for extended socket options
|
|
||||||
* together with some other static utilities
|
|
||||||
*/
|
|
||||||
public class ExtendedOptionsImpl {
|
|
||||||
|
|
||||||
static {
|
|
||||||
AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
|
|
||||||
System.loadLibrary("net");
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ExtendedOptionsImpl() {}
|
|
||||||
|
|
||||||
public static void checkSetOptionPermission(SocketOption<?> option) {
|
|
||||||
SecurityManager sm = System.getSecurityManager();
|
|
||||||
if (sm == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String check = "setOption." + option.name();
|
|
||||||
sm.checkPermission(new NetworkPermission(check));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void checkGetOptionPermission(SocketOption<?> option) {
|
|
||||||
SecurityManager sm = System.getSecurityManager();
|
|
||||||
if (sm == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String check = "getOption." + option.name();
|
|
||||||
sm.checkPermission(new NetworkPermission(check));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void checkValueType(Object value, Class<?> type) {
|
|
||||||
if (!type.isAssignableFrom(value.getClass())) {
|
|
||||||
String s = "Found: " + value.getClass().toString() + " Expected: "
|
|
||||||
+ type.toString();
|
|
||||||
throw new IllegalArgumentException(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static native void init();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Extension native implementations
|
|
||||||
*
|
|
||||||
* SO_FLOW_SLA
|
|
||||||
*/
|
|
||||||
public static native void setFlowOption(FileDescriptor fd, SocketFlow f);
|
|
||||||
public static native void getFlowOption(FileDescriptor fd, SocketFlow f);
|
|
||||||
public static native boolean flowSupported();
|
|
||||||
}
|
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.net.ext;
|
||||||
|
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.net.SocketOption;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the infrastructure to support extended socket options, beyond those
|
||||||
|
* defined in {@link java.net.StandardSocketOptions}.
|
||||||
|
*
|
||||||
|
* Extended socket options are accessed through the jdk.net API, which is in
|
||||||
|
* the jdk.net module.
|
||||||
|
*/
|
||||||
|
public abstract class ExtendedSocketOptions {
|
||||||
|
|
||||||
|
private final Set<SocketOption<?>> options;
|
||||||
|
|
||||||
|
/** Tells whether or not the option is supported. */
|
||||||
|
public final boolean isOptionSupported(SocketOption<?> option) {
|
||||||
|
return options().contains(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the, possibly empty, set of extended socket options available. */
|
||||||
|
public final Set<SocketOption<?>> options() { return options; }
|
||||||
|
|
||||||
|
/** Sets the value of a socket option, for the given socket. */
|
||||||
|
public abstract void setOption(FileDescriptor fd, SocketOption<?> option, Object value)
|
||||||
|
throws SocketException;
|
||||||
|
|
||||||
|
/** Returns the value of a socket option, for the given socket. */
|
||||||
|
public abstract Object getOption(FileDescriptor fd, SocketOption<?> option)
|
||||||
|
throws SocketException;
|
||||||
|
|
||||||
|
protected ExtendedSocketOptions(Set<SocketOption<?>> options) {
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static volatile ExtendedSocketOptions instance;
|
||||||
|
|
||||||
|
public static final ExtendedSocketOptions getInstance() { return instance; }
|
||||||
|
|
||||||
|
/** Registers support for extended socket options. Invoked by the jdk.net module. */
|
||||||
|
public static final void register(ExtendedSocketOptions extOptions) {
|
||||||
|
if (instance != null)
|
||||||
|
throw new InternalError("Attempting to reregister extended options");
|
||||||
|
|
||||||
|
instance = extOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
// If the class is present, it will be initialized which
|
||||||
|
// triggers registration of the extended socket options.
|
||||||
|
Class<?> c = Class.forName("jdk.net.ExtendedSocketOptions");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// the jdk.net module is not present => no extended socket options
|
||||||
|
instance = new NoExtendedSocketOptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class NoExtendedSocketOptions extends ExtendedSocketOptions {
|
||||||
|
|
||||||
|
NoExtendedSocketOptions() {
|
||||||
|
super(Collections.<SocketOption<?>>emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOption(FileDescriptor fd, SocketOption<?> option, Object value)
|
||||||
|
throws SocketException
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"no extended options: " + option.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getOption(FileDescriptor fd, SocketOption<?> option)
|
||||||
|
throws SocketException
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"no extended options: " + option.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -39,7 +39,7 @@ import java.util.Collections;
|
|||||||
import java.util.concurrent.*;
|
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.ExtendedOptionsImpl;
|
import sun.net.ext.ExtendedSocketOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base implementation of AsynchronousSocketChannel
|
* Base implementation of AsynchronousSocketChannel
|
||||||
@ -512,9 +512,9 @@ abstract class AsynchronousSocketChannelImpl
|
|||||||
set.add(StandardSocketOptions.SO_REUSEPORT);
|
set.add(StandardSocketOptions.SO_REUSEPORT);
|
||||||
}
|
}
|
||||||
set.add(StandardSocketOptions.TCP_NODELAY);
|
set.add(StandardSocketOptions.TCP_NODELAY);
|
||||||
if (ExtendedOptionsImpl.flowSupported()) {
|
ExtendedSocketOptions extendedOptions =
|
||||||
set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
|
ExtendedSocketOptions.getInstance();
|
||||||
}
|
set.addAll(extendedOptions.options());
|
||||||
return Collections.unmodifiableSet(set);
|
return Collections.unmodifiableSet(set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import java.nio.channels.*;
|
|||||||
import java.nio.channels.spi.*;
|
import java.nio.channels.spi.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import sun.net.ResourceManager;
|
import sun.net.ResourceManager;
|
||||||
import sun.net.ExtendedOptionsImpl;
|
import sun.net.ext.ExtendedSocketOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of DatagramChannels.
|
* An implementation of DatagramChannels.
|
||||||
@ -306,9 +306,9 @@ 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);
|
||||||
if (ExtendedOptionsImpl.flowSupported()) {
|
ExtendedSocketOptions extendedOptions =
|
||||||
set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
|
ExtendedSocketOptions.getInstance();
|
||||||
}
|
set.addAll(extendedOptions.options());
|
||||||
return Collections.unmodifiableSet(set);
|
return Collections.unmodifiableSet(set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,15 +27,13 @@ package sun.nio.ch;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import jdk.net.*;
|
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
import sun.net.ExtendedOptionsImpl;
|
import sun.net.ext.ExtendedSocketOptions;
|
||||||
import sun.security.action.GetPropertyAction;
|
import sun.security.action.GetPropertyAction;
|
||||||
|
|
||||||
|
|
||||||
public class Net {
|
public class Net {
|
||||||
|
|
||||||
private Net() { }
|
private Net() { }
|
||||||
@ -281,6 +279,9 @@ public class Net {
|
|||||||
|
|
||||||
// -- Socket options
|
// -- Socket options
|
||||||
|
|
||||||
|
static final ExtendedSocketOptions extendedOptions =
|
||||||
|
ExtendedSocketOptions.getInstance();
|
||||||
|
|
||||||
static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
|
static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
|
||||||
SocketOption<?> name, Object value)
|
SocketOption<?> name, Object value)
|
||||||
throws IOException
|
throws IOException
|
||||||
@ -291,12 +292,8 @@ public class Net {
|
|||||||
// only simple values supported by this method
|
// only simple values supported by this method
|
||||||
Class<?> type = name.type();
|
Class<?> type = name.type();
|
||||||
|
|
||||||
if (type == SocketFlow.class) {
|
if (extendedOptions.isOptionSupported(name)) {
|
||||||
SecurityManager sm = System.getSecurityManager();
|
extendedOptions.setOption(fd, name, value);
|
||||||
if (sm != null) {
|
|
||||||
sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA"));
|
|
||||||
}
|
|
||||||
ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,14 +350,8 @@ public class Net {
|
|||||||
{
|
{
|
||||||
Class<?> type = name.type();
|
Class<?> type = name.type();
|
||||||
|
|
||||||
if (type == SocketFlow.class) {
|
if (extendedOptions.isOptionSupported(name)) {
|
||||||
SecurityManager sm = System.getSecurityManager();
|
return extendedOptions.getOption(fd, name);
|
||||||
if (sm != null) {
|
|
||||||
sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA"));
|
|
||||||
}
|
|
||||||
SocketFlow flow = SocketFlow.create();
|
|
||||||
ExtendedOptionsImpl.getFlowOption(fd, flow);
|
|
||||||
return flow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// only simple values supported by this method
|
// only simple values supported by this method
|
||||||
|
@ -33,8 +33,7 @@ import java.nio.channels.*;
|
|||||||
import java.nio.channels.spi.*;
|
import java.nio.channels.spi.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import sun.net.NetHooks;
|
import sun.net.NetHooks;
|
||||||
import sun.net.ExtendedOptionsImpl;
|
import sun.net.ext.ExtendedSocketOptions;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of SocketChannels
|
* An implementation of SocketChannels
|
||||||
@ -242,9 +241,9 @@ 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);
|
||||||
if (ExtendedOptionsImpl.flowSupported()) {
|
ExtendedSocketOptions extendedOptions =
|
||||||
set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
|
ExtendedSocketOptions.getInstance();
|
||||||
}
|
set.addAll(extendedOptions.options());
|
||||||
return Collections.unmodifiableSet(set);
|
return Collections.unmodifiableSet(set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,7 @@ package java.net;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Collections;
|
import sun.net.ext.ExtendedSocketOptions;
|
||||||
import jdk.net.*;
|
|
||||||
import static sun.net.ExtendedOptionsImpl.*;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On Unix systems we simply delegate to native methods.
|
* On Unix systems we simply delegate to native methods.
|
||||||
@ -43,8 +41,11 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final ExtendedSocketOptions extendedOptions =
|
||||||
|
ExtendedSocketOptions.getInstance();
|
||||||
|
|
||||||
protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
|
protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
|
||||||
if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
|
if (!extendedOptions.isOptionSupported(name)) {
|
||||||
if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
|
if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
|
||||||
super.setOption(name, value);
|
super.setOption(name, value);
|
||||||
} else {
|
} else {
|
||||||
@ -55,21 +56,16 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!flowSupported()) {
|
|
||||||
throw new UnsupportedOperationException("unsupported option");
|
|
||||||
}
|
|
||||||
if (isClosed()) {
|
if (isClosed()) {
|
||||||
throw new SocketException("Socket closed");
|
throw new SocketException("Socket closed");
|
||||||
}
|
}
|
||||||
checkSetOptionPermission(name);
|
extendedOptions.setOption(fd, name, value);
|
||||||
checkValueType(value, SocketFlow.class);
|
|
||||||
setFlowOption(getFileDescriptor(), (SocketFlow)value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> T getOption(SocketOption<T> name) throws IOException {
|
protected <T> T getOption(SocketOption<T> name) throws IOException {
|
||||||
if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
|
if (!extendedOptions.isOptionSupported(name)) {
|
||||||
if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
|
if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
|
||||||
return super.getOption(name);
|
return super.getOption(name);
|
||||||
} else {
|
} else {
|
||||||
@ -79,31 +75,23 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
|
|||||||
throw new UnsupportedOperationException("unsupported option");
|
throw new UnsupportedOperationException("unsupported option");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (isClosed()) {
|
||||||
|
throw new SocketException("Socket closed");
|
||||||
|
}
|
||||||
|
return (T) extendedOptions.getOption(fd, name);
|
||||||
}
|
}
|
||||||
if (!flowSupported()) {
|
|
||||||
throw new UnsupportedOperationException("unsupported option");
|
|
||||||
}
|
|
||||||
if (isClosed()) {
|
|
||||||
throw new SocketException("Socket closed");
|
|
||||||
}
|
|
||||||
checkGetOptionPermission(name);
|
|
||||||
SocketFlow flow = SocketFlow.create();
|
|
||||||
getFlowOption(getFileDescriptor(), flow);
|
|
||||||
return (T)flow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<SocketOption<?>> supportedOptions() {
|
protected Set<SocketOption<?>> supportedOptions() {
|
||||||
HashSet<SocketOption<?>> options = new HashSet<>(
|
HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions());
|
||||||
super.supportedOptions());
|
options.addAll(extendedOptions.options());
|
||||||
|
|
||||||
if (flowSupported()) {
|
|
||||||
options.add(ExtendedSocketOptions.SO_FLOW_SLA);
|
|
||||||
}
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void socketSetOption(int opt, Object val) throws SocketException {
|
protected void socketSetOption(int opt, Object val) throws SocketException {
|
||||||
if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
|
if (opt == SocketOptions.SO_REUSEPORT &&
|
||||||
|
!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
|
||||||
throw new UnsupportedOperationException("unsupported option");
|
throw new UnsupportedOperationException("unsupported option");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -28,10 +28,7 @@ import java.io.IOException;
|
|||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Collections;
|
import sun.net.ext.ExtendedSocketOptions;
|
||||||
import jdk.net.*;
|
|
||||||
|
|
||||||
import static sun.net.ExtendedOptionsImpl.*;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On Unix systems we simply delegate to native methods.
|
* On Unix systems we simply delegate to native methods.
|
||||||
@ -57,8 +54,11 @@ class PlainSocketImpl extends AbstractPlainSocketImpl
|
|||||||
this.fd = fd;
|
this.fd = fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final ExtendedSocketOptions extendedOptions =
|
||||||
|
ExtendedSocketOptions.getInstance();
|
||||||
|
|
||||||
protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
|
protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
|
||||||
if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
|
if (!extendedOptions.isOptionSupported(name)) {
|
||||||
if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
|
if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
|
||||||
super.setOption(name, value);
|
super.setOption(name, value);
|
||||||
} else {
|
} else {
|
||||||
@ -69,21 +69,19 @@ class PlainSocketImpl extends AbstractPlainSocketImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (getSocket() == null || !flowSupported()) {
|
if (getSocket() == null) {
|
||||||
throw new UnsupportedOperationException("unsupported option");
|
throw new UnsupportedOperationException("unsupported option");
|
||||||
}
|
}
|
||||||
if (isClosedOrPending()) {
|
if (isClosedOrPending()) {
|
||||||
throw new SocketException("Socket closed");
|
throw new SocketException("Socket closed");
|
||||||
}
|
}
|
||||||
checkSetOptionPermission(name);
|
extendedOptions.setOption(fd, name, value);
|
||||||
checkValueType(value, SocketFlow.class);
|
|
||||||
setFlowOption(getFileDescriptor(), (SocketFlow)value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> T getOption(SocketOption<T> name) throws IOException {
|
protected <T> T getOption(SocketOption<T> name) throws IOException {
|
||||||
if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
|
if (!extendedOptions.isOptionSupported(name)) {
|
||||||
if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
|
if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
|
||||||
return super.getOption(name);
|
return super.getOption(name);
|
||||||
} else {
|
} else {
|
||||||
@ -93,31 +91,28 @@ class PlainSocketImpl extends AbstractPlainSocketImpl
|
|||||||
throw new UnsupportedOperationException("unsupported option");
|
throw new UnsupportedOperationException("unsupported option");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (getSocket() == null) {
|
||||||
|
throw new UnsupportedOperationException("unsupported option");
|
||||||
|
}
|
||||||
|
if (isClosedOrPending()) {
|
||||||
|
throw new SocketException("Socket closed");
|
||||||
|
}
|
||||||
|
return (T) extendedOptions.getOption(fd, name);
|
||||||
}
|
}
|
||||||
if (getSocket() == null || !flowSupported()) {
|
|
||||||
throw new UnsupportedOperationException("unsupported option");
|
|
||||||
}
|
|
||||||
if (isClosedOrPending()) {
|
|
||||||
throw new SocketException("Socket closed");
|
|
||||||
}
|
|
||||||
checkGetOptionPermission(name);
|
|
||||||
SocketFlow flow = SocketFlow.create();
|
|
||||||
getFlowOption(getFileDescriptor(), flow);
|
|
||||||
return (T)flow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<SocketOption<?>> supportedOptions() {
|
protected Set<SocketOption<?>> supportedOptions() {
|
||||||
HashSet<SocketOption<?>> options = new HashSet<>(
|
HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions());
|
||||||
super.supportedOptions());
|
if (getSocket() != null) {
|
||||||
|
options.addAll(extendedOptions.options());
|
||||||
if (getSocket() != null && flowSupported()) {
|
|
||||||
options.add(ExtendedSocketOptions.SO_FLOW_SLA);
|
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
|
if (opt == SocketOptions.SO_REUSEPORT &&
|
||||||
|
!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
|
||||||
throw new UnsupportedOperationException("unsupported option");
|
throw new UnsupportedOperationException("unsupported option");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -1,344 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014, 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
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "net_util.h"
|
|
||||||
#include "jdk_net_SocketFlow.h"
|
|
||||||
|
|
||||||
static jclass sf_status_class; /* Status enum type */
|
|
||||||
|
|
||||||
static jfieldID sf_status;
|
|
||||||
static jfieldID sf_priority;
|
|
||||||
static jfieldID sf_bandwidth;
|
|
||||||
|
|
||||||
static jfieldID sf_fd_fdID; /* FileDescriptor.fd */
|
|
||||||
|
|
||||||
/* References to the literal enum values */
|
|
||||||
|
|
||||||
static jobject sfs_NOSTATUS;
|
|
||||||
static jobject sfs_OK;
|
|
||||||
static jobject sfs_NOPERMISSION;
|
|
||||||
static jobject sfs_NOTCONNECTED;
|
|
||||||
static jobject sfs_NOTSUPPORTED;
|
|
||||||
static jobject sfs_ALREADYCREATED;
|
|
||||||
static jobject sfs_INPROGRESS;
|
|
||||||
static jobject sfs_OTHER;
|
|
||||||
|
|
||||||
static jobject getEnumField(JNIEnv *env, char *name);
|
|
||||||
static void setStatus(JNIEnv *env, jobject obj, int errval);
|
|
||||||
|
|
||||||
/* OS specific code is implemented in these three functions */
|
|
||||||
|
|
||||||
static jboolean flowSupported0() ;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: sun_net_ExtendedOptionsImpl
|
|
||||||
* Method: init
|
|
||||||
* Signature: ()V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init
|
|
||||||
(JNIEnv *env, jclass UNUSED)
|
|
||||||
{
|
|
||||||
static int initialized = 0;
|
|
||||||
jclass c;
|
|
||||||
|
|
||||||
/* Global class references */
|
|
||||||
|
|
||||||
if (initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status");
|
|
||||||
CHECK_NULL(c);
|
|
||||||
sf_status_class = (*env)->NewGlobalRef(env, c);
|
|
||||||
CHECK_NULL(sf_status_class);
|
|
||||||
|
|
||||||
/* int "fd" field of java.io.FileDescriptor */
|
|
||||||
|
|
||||||
c = (*env)->FindClass(env, "java/io/FileDescriptor");
|
|
||||||
CHECK_NULL(c);
|
|
||||||
sf_fd_fdID = (*env)->GetFieldID(env, c, "fd", "I");
|
|
||||||
CHECK_NULL(sf_fd_fdID);
|
|
||||||
|
|
||||||
|
|
||||||
/* SocketFlow fields */
|
|
||||||
|
|
||||||
c = (*env)->FindClass(env, "jdk/net/SocketFlow");
|
|
||||||
CHECK_NULL(c);
|
|
||||||
|
|
||||||
/* status */
|
|
||||||
|
|
||||||
sf_status = (*env)->GetFieldID(env, c, "status",
|
|
||||||
"Ljdk/net/SocketFlow$Status;");
|
|
||||||
CHECK_NULL(sf_status);
|
|
||||||
|
|
||||||
/* priority */
|
|
||||||
|
|
||||||
sf_priority = (*env)->GetFieldID(env, c, "priority", "I");
|
|
||||||
CHECK_NULL(sf_priority);
|
|
||||||
|
|
||||||
/* bandwidth */
|
|
||||||
|
|
||||||
sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J");
|
|
||||||
CHECK_NULL(sf_bandwidth);
|
|
||||||
|
|
||||||
/* Initialize the static enum values */
|
|
||||||
|
|
||||||
sfs_NOSTATUS = getEnumField(env, "NO_STATUS");
|
|
||||||
CHECK_NULL(sfs_NOSTATUS);
|
|
||||||
sfs_OK = getEnumField(env, "OK");
|
|
||||||
CHECK_NULL(sfs_OK);
|
|
||||||
sfs_NOPERMISSION = getEnumField(env, "NO_PERMISSION");
|
|
||||||
CHECK_NULL(sfs_NOPERMISSION);
|
|
||||||
sfs_NOTCONNECTED = getEnumField(env, "NOT_CONNECTED");
|
|
||||||
CHECK_NULL(sfs_NOTCONNECTED);
|
|
||||||
sfs_NOTSUPPORTED = getEnumField(env, "NOT_SUPPORTED");
|
|
||||||
CHECK_NULL(sfs_NOTSUPPORTED);
|
|
||||||
sfs_ALREADYCREATED = getEnumField(env, "ALREADY_CREATED");
|
|
||||||
CHECK_NULL(sfs_ALREADYCREATED);
|
|
||||||
sfs_INPROGRESS = getEnumField(env, "IN_PROGRESS");
|
|
||||||
CHECK_NULL(sfs_INPROGRESS);
|
|
||||||
sfs_OTHER = getEnumField(env, "OTHER");
|
|
||||||
CHECK_NULL(sfs_OTHER);
|
|
||||||
initialized = JNI_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jobject getEnumField(JNIEnv *env, char *name)
|
|
||||||
{
|
|
||||||
jobject f;
|
|
||||||
jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name,
|
|
||||||
"Ljdk/net/SocketFlow$Status;");
|
|
||||||
CHECK_NULL_RETURN(fID, NULL);
|
|
||||||
|
|
||||||
f = (*env)->GetStaticObjectField(env, sf_status_class, fID);
|
|
||||||
CHECK_NULL_RETURN(f, NULL);
|
|
||||||
f = (*env)->NewGlobalRef(env, f);
|
|
||||||
CHECK_NULL_RETURN(f, NULL);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Retrieve the int file-descriptor from a public socket type object.
|
|
||||||
* Gets impl, then the FileDescriptor from the impl, and then the fd
|
|
||||||
* from that.
|
|
||||||
*/
|
|
||||||
static int getFD(JNIEnv *env, jobject fileDesc) {
|
|
||||||
return (*env)->GetIntField(env, fileDesc, sf_fd_fdID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the status field of a SocketFlow to one of the
|
|
||||||
* canned enum values
|
|
||||||
*/
|
|
||||||
static void setStatus (JNIEnv *env, jobject obj, int errval)
|
|
||||||
{
|
|
||||||
switch (errval) {
|
|
||||||
case 0: /* OK */
|
|
||||||
(*env)->SetObjectField(env, obj, sf_status, sfs_OK);
|
|
||||||
break;
|
|
||||||
case EPERM:
|
|
||||||
(*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION);
|
|
||||||
break;
|
|
||||||
case ENOTCONN:
|
|
||||||
(*env)->SetObjectField(env, obj, sf_status, sfs_NOTCONNECTED);
|
|
||||||
break;
|
|
||||||
case EOPNOTSUPP:
|
|
||||||
(*env)->SetObjectField(env, obj, sf_status, sfs_NOTSUPPORTED);
|
|
||||||
break;
|
|
||||||
case EALREADY:
|
|
||||||
(*env)->SetObjectField(env, obj, sf_status, sfs_ALREADYCREATED);
|
|
||||||
break;
|
|
||||||
case EINPROGRESS:
|
|
||||||
(*env)->SetObjectField(env, obj, sf_status, sfs_INPROGRESS);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
(*env)->SetObjectField(env, obj, sf_status, sfs_OTHER);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __solaris__
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: sun_net_ExtendedOptionsImpl
|
|
||||||
* Method: setFlowOption
|
|
||||||
* Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
|
|
||||||
(JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
|
|
||||||
{
|
|
||||||
int fd = getFD(env, fileDesc);
|
|
||||||
|
|
||||||
if (fd < 0) {
|
|
||||||
NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
sock_flow_props_t props;
|
|
||||||
jlong bandwidth;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
jint priority = (*env)->GetIntField(env, flow, sf_priority);
|
|
||||||
memset(&props, 0, sizeof(props));
|
|
||||||
props.sfp_version = SOCK_FLOW_PROP_VERSION1;
|
|
||||||
|
|
||||||
if (priority != jdk_net_SocketFlow_UNSET) {
|
|
||||||
props.sfp_mask |= SFP_PRIORITY;
|
|
||||||
props.sfp_priority = priority;
|
|
||||||
}
|
|
||||||
bandwidth = (*env)->GetLongField(env, flow, sf_bandwidth);
|
|
||||||
if (bandwidth > -1) {
|
|
||||||
props.sfp_mask |= SFP_MAXBW;
|
|
||||||
props.sfp_maxbw = (uint64_t) bandwidth;
|
|
||||||
}
|
|
||||||
rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
|
|
||||||
if (rv < 0) {
|
|
||||||
if (errno == ENOPROTOOPT) {
|
|
||||||
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
|
|
||||||
"unsupported socket option");
|
|
||||||
} else if (errno == EACCES || errno == EPERM) {
|
|
||||||
NET_ERROR(env, JNU_JAVANETPKG "SocketException",
|
|
||||||
"Permission denied");
|
|
||||||
} else {
|
|
||||||
NET_ERROR(env, JNU_JAVANETPKG "SocketException",
|
|
||||||
"set option SO_FLOW_SLA failed");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setStatus(env, flow, props.sfp_status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: sun_net_ExtendedOptionsImpl
|
|
||||||
* Method: getFlowOption
|
|
||||||
* Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
|
|
||||||
(JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
|
|
||||||
{
|
|
||||||
int fd = getFD(env, fileDesc);
|
|
||||||
|
|
||||||
if (fd < 0) {
|
|
||||||
NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
sock_flow_props_t props;
|
|
||||||
int status;
|
|
||||||
socklen_t sz = sizeof(props);
|
|
||||||
|
|
||||||
int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz);
|
|
||||||
if (rv < 0) {
|
|
||||||
if (errno == ENOPROTOOPT) {
|
|
||||||
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
|
|
||||||
"unsupported socket option");
|
|
||||||
} else if (errno == EACCES || errno == EPERM) {
|
|
||||||
NET_ERROR(env, JNU_JAVANETPKG "SocketException",
|
|
||||||
"Permission denied");
|
|
||||||
} else {
|
|
||||||
NET_ERROR(env, JNU_JAVANETPKG "SocketException",
|
|
||||||
"set option SO_FLOW_SLA failed");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* first check status to see if flow exists */
|
|
||||||
status = props.sfp_status;
|
|
||||||
setStatus(env, flow, status);
|
|
||||||
if (status == 0) { /* OK */
|
|
||||||
/* can set the other fields now */
|
|
||||||
if (props.sfp_mask & SFP_PRIORITY) {
|
|
||||||
(*env)->SetIntField(env, flow, sf_priority, props.sfp_priority);
|
|
||||||
}
|
|
||||||
if (props.sfp_mask & SFP_MAXBW) {
|
|
||||||
(*env)->SetLongField(env, flow, sf_bandwidth,
|
|
||||||
(jlong)props.sfp_maxbw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static jboolean flowsupported;
|
|
||||||
static jboolean flowsupported_set = JNI_FALSE;
|
|
||||||
|
|
||||||
static jboolean flowSupported0()
|
|
||||||
{
|
|
||||||
/* Do a simple dummy call, and try to figure out from that */
|
|
||||||
sock_flow_props_t props;
|
|
||||||
int rv, s;
|
|
||||||
if (flowsupported_set) {
|
|
||||||
return flowsupported;
|
|
||||||
}
|
|
||||||
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
if (s < 0) {
|
|
||||||
flowsupported = JNI_FALSE;
|
|
||||||
flowsupported_set = JNI_TRUE;
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
memset(&props, 0, sizeof(props));
|
|
||||||
props.sfp_version = SOCK_FLOW_PROP_VERSION1;
|
|
||||||
props.sfp_mask |= SFP_PRIORITY;
|
|
||||||
props.sfp_priority = SFP_PRIO_NORMAL;
|
|
||||||
rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
|
|
||||||
if (rv != 0 && errno == ENOPROTOOPT) {
|
|
||||||
rv = JNI_FALSE;
|
|
||||||
} else {
|
|
||||||
rv = JNI_TRUE;
|
|
||||||
}
|
|
||||||
close(s);
|
|
||||||
flowsupported = rv;
|
|
||||||
flowsupported_set = JNI_TRUE;
|
|
||||||
return flowsupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* __solaris__ */
|
|
||||||
|
|
||||||
/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
|
|
||||||
(JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
|
|
||||||
{
|
|
||||||
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
|
|
||||||
"unsupported socket option");
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
|
|
||||||
(JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
|
|
||||||
{
|
|
||||||
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
|
|
||||||
"unsupported socket option");
|
|
||||||
}
|
|
||||||
|
|
||||||
static jboolean flowSupported0() {
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __solaris__ */
|
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported
|
|
||||||
(JNIEnv *env, jclass UNUSED)
|
|
||||||
{
|
|
||||||
return flowSupported0();
|
|
||||||
}
|
|
@ -120,47 +120,6 @@ int getDefaultIPv6Interface(struct in6_addr *target_addr);
|
|||||||
|
|
||||||
#ifdef __solaris__
|
#ifdef __solaris__
|
||||||
int net_getParam(char *driver, char *param);
|
int net_getParam(char *driver, char *param);
|
||||||
|
|
||||||
#ifndef SO_FLOW_SLA
|
|
||||||
#define SO_FLOW_SLA 0x1018
|
|
||||||
|
|
||||||
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
|
|
||||||
#pragma pack(4)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Used with the setsockopt(SO_FLOW_SLA, ...) call to set
|
|
||||||
* per socket service level properties.
|
|
||||||
* When the application uses per-socket API, we will enforce the properties
|
|
||||||
* on both outbound and inbound packets.
|
|
||||||
*
|
|
||||||
* For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1.
|
|
||||||
*/
|
|
||||||
typedef struct sock_flow_props_s {
|
|
||||||
int sfp_version;
|
|
||||||
uint32_t sfp_mask;
|
|
||||||
int sfp_priority; /* flow priority */
|
|
||||||
uint64_t sfp_maxbw; /* bandwidth limit in bps */
|
|
||||||
int sfp_status; /* flow create status for getsockopt */
|
|
||||||
} sock_flow_props_t;
|
|
||||||
|
|
||||||
#define SOCK_FLOW_PROP_VERSION1 1
|
|
||||||
|
|
||||||
/* bit mask values for sfp_mask */
|
|
||||||
#define SFP_MAXBW 0x00000001 /* Flow Bandwidth Limit */
|
|
||||||
#define SFP_PRIORITY 0x00000008 /* Flow priority */
|
|
||||||
|
|
||||||
/* possible values for sfp_priority */
|
|
||||||
#define SFP_PRIO_NORMAL 1
|
|
||||||
#define SFP_PRIO_HIGH 2
|
|
||||||
|
|
||||||
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
|
|
||||||
#pragma pack()
|
|
||||||
#endif /* _LONG_LONG_ALIGNMENT */
|
|
||||||
|
|
||||||
#endif /* SO_FLOW_SLA */
|
|
||||||
#endif /* __solaris__ */
|
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL NET_IsFlowSupported();
|
|
||||||
|
|
||||||
#endif /* NET_UTILS_MD_H */
|
#endif /* NET_UTILS_MD_H */
|
||||||
|
212
jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java
Normal file
212
jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jdk.net;
|
||||||
|
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.net.SocketOption;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import jdk.internal.misc.JavaIOFileDescriptorAccess;
|
||||||
|
import jdk.internal.misc.SharedSecrets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines extended socket options, beyond those defined in
|
||||||
|
* {@link java.net.StandardSocketOptions}. These options may be platform
|
||||||
|
* specific.
|
||||||
|
*
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public final class ExtendedSocketOptions {
|
||||||
|
|
||||||
|
private static class ExtSocketOption<T> implements SocketOption<T> {
|
||||||
|
private final String name;
|
||||||
|
private final Class<T> type;
|
||||||
|
ExtSocketOption(String name, Class<T> type) {
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
@Override public String name() { return name; }
|
||||||
|
@Override public Class<T> type() { return type; }
|
||||||
|
@Override public String toString() { return name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private ExtendedSocketOptions() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service level properties. When a security manager is installed,
|
||||||
|
* setting or getting this option requires a {@link NetworkPermission}
|
||||||
|
* {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"}
|
||||||
|
* respectively.
|
||||||
|
*/
|
||||||
|
public static final SocketOption<SocketFlow> SO_FLOW_SLA = new
|
||||||
|
ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class);
|
||||||
|
|
||||||
|
|
||||||
|
private static final PlatformSocketOptions platformSocketOptions =
|
||||||
|
PlatformSocketOptions.get();
|
||||||
|
|
||||||
|
private static final boolean flowSupported =
|
||||||
|
platformSocketOptions.flowSupported();
|
||||||
|
|
||||||
|
private static final Set<SocketOption<?>> extendedOptions = options();
|
||||||
|
|
||||||
|
static Set<SocketOption<?>> options() {
|
||||||
|
if (flowSupported)
|
||||||
|
return Set.of(SO_FLOW_SLA);
|
||||||
|
else
|
||||||
|
return Collections.<SocketOption<?>>emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Registers the extended socket options with the base module.
|
||||||
|
sun.net.ext.ExtendedSocketOptions.register(
|
||||||
|
new sun.net.ext.ExtendedSocketOptions(extendedOptions) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOption(FileDescriptor fd,
|
||||||
|
SocketOption<?> option,
|
||||||
|
Object value)
|
||||||
|
throws SocketException
|
||||||
|
{
|
||||||
|
SecurityManager sm = System.getSecurityManager();
|
||||||
|
if (sm != null)
|
||||||
|
sm.checkPermission(new NetworkPermission("setOption." + option.name()));
|
||||||
|
|
||||||
|
if (fd == null || !fd.valid())
|
||||||
|
throw new SocketException("socket closed");
|
||||||
|
|
||||||
|
if (option == SO_FLOW_SLA) {
|
||||||
|
assert flowSupported;
|
||||||
|
SocketFlow flow = checkValueType(value, option.type());
|
||||||
|
setFlowOption(fd, flow);
|
||||||
|
} else {
|
||||||
|
throw new InternalError("Unexpected option " + option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getOption(FileDescriptor fd,
|
||||||
|
SocketOption<?> option)
|
||||||
|
throws SocketException
|
||||||
|
{
|
||||||
|
SecurityManager sm = System.getSecurityManager();
|
||||||
|
if (sm != null)
|
||||||
|
sm.checkPermission(new NetworkPermission("getOption." + option.name()));
|
||||||
|
|
||||||
|
if (fd == null || !fd.valid())
|
||||||
|
throw new SocketException("socket closed");
|
||||||
|
|
||||||
|
if (option == SO_FLOW_SLA) {
|
||||||
|
assert flowSupported;
|
||||||
|
SocketFlow flow = SocketFlow.create();
|
||||||
|
getFlowOption(fd, flow);
|
||||||
|
return flow;
|
||||||
|
} else {
|
||||||
|
throw new InternalError("Unexpected option " + option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <T> T checkValueType(Object value, Class<?> type) {
|
||||||
|
if (!type.isAssignableFrom(value.getClass())) {
|
||||||
|
String s = "Found: " + value.getClass() + ", Expected: " + type;
|
||||||
|
throw new IllegalArgumentException(s);
|
||||||
|
}
|
||||||
|
return (T) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final JavaIOFileDescriptorAccess fdAccess =
|
||||||
|
SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||||
|
|
||||||
|
private static void setFlowOption(FileDescriptor fd, SocketFlow f)
|
||||||
|
throws SocketException
|
||||||
|
{
|
||||||
|
int status = platformSocketOptions.setFlowOption(fdAccess.get(fd),
|
||||||
|
f.priority(),
|
||||||
|
f.bandwidth());
|
||||||
|
f.status(status); // augment the given flow with the status
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void getFlowOption(FileDescriptor fd, SocketFlow f)
|
||||||
|
throws SocketException
|
||||||
|
{
|
||||||
|
int status = platformSocketOptions.getFlowOption(fdAccess.get(fd), f);
|
||||||
|
f.status(status); // augment the given flow with the status
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PlatformSocketOptions {
|
||||||
|
|
||||||
|
protected PlatformSocketOptions() {}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static PlatformSocketOptions newInstance(String cn) {
|
||||||
|
Class<PlatformSocketOptions> c;
|
||||||
|
try {
|
||||||
|
c = (Class<PlatformSocketOptions>)Class.forName(cn);
|
||||||
|
return c.getConstructor(new Class<?>[] { }).newInstance();
|
||||||
|
} catch (ReflectiveOperationException x) {
|
||||||
|
throw new AssertionError(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PlatformSocketOptions create() {
|
||||||
|
String osname = AccessController.doPrivileged(
|
||||||
|
new PrivilegedAction<String>() {
|
||||||
|
public String run() {
|
||||||
|
return System.getProperty("os.name");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if ("SunOS".equals(osname))
|
||||||
|
return newInstance("jdk.net.SolarisSocketOptions");
|
||||||
|
return new PlatformSocketOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final PlatformSocketOptions instance = create();
|
||||||
|
|
||||||
|
static PlatformSocketOptions get() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setFlowOption(int fd, int priority, long bandwidth)
|
||||||
|
throws SocketException
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException("unsupported socket option");
|
||||||
|
}
|
||||||
|
|
||||||
|
int getFlowOption(int fd, SocketFlow f) throws SocketException {
|
||||||
|
throw new UnsupportedOperationException("unsupported socket option");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean flowSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -47,17 +47,18 @@ import java.lang.annotation.Native;
|
|||||||
*/
|
*/
|
||||||
public class SocketFlow {
|
public class SocketFlow {
|
||||||
|
|
||||||
private static final int UNSET = -1;
|
@Native public static final int UNSET = -1;
|
||||||
@Native public static final int NORMAL_PRIORITY = 1;
|
@Native public static final int NORMAL_PRIORITY = 1;
|
||||||
@Native public static final int HIGH_PRIORITY = 2;
|
@Native public static final int HIGH_PRIORITY = 2;
|
||||||
|
|
||||||
private int priority = NORMAL_PRIORITY;
|
@Native private static final int NO_STATUS_VALUE = 0;
|
||||||
|
@Native private static final int OK_VALUE = 1;
|
||||||
private long bandwidth = UNSET;
|
@Native private static final int NO_PERMISSION_VALUE = 2;
|
||||||
|
@Native private static final int NOT_CONNECTED_VALUE = 3;
|
||||||
private Status status = Status.NO_STATUS;
|
@Native private static final int NOT_SUPPORTED_VALUE = 4;
|
||||||
|
@Native private static final int ALREADY_CREATED_VALUE = 5;
|
||||||
private SocketFlow() {}
|
@Native private static final int IN_PROGRESS_VALUE = 6;
|
||||||
|
@Native private static final int OTHER_VALUE = 7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enumeration of the return values from the SO_FLOW_SLA
|
* Enumeration of the return values from the SO_FLOW_SLA
|
||||||
@ -72,37 +73,56 @@ public class SocketFlow {
|
|||||||
* Set or get socket option has not been called yet. Status
|
* Set or get socket option has not been called yet. Status
|
||||||
* values can only be retrieved after calling set or get.
|
* values can only be retrieved after calling set or get.
|
||||||
*/
|
*/
|
||||||
NO_STATUS,
|
NO_STATUS(NO_STATUS_VALUE),
|
||||||
/**
|
/**
|
||||||
* Flow successfully created.
|
* Flow successfully created.
|
||||||
*/
|
*/
|
||||||
OK,
|
OK(OK_VALUE),
|
||||||
/**
|
/**
|
||||||
* Caller has no permission to create flow.
|
* Caller has no permission to create flow.
|
||||||
*/
|
*/
|
||||||
NO_PERMISSION,
|
NO_PERMISSION(NO_PERMISSION_VALUE),
|
||||||
/**
|
/**
|
||||||
* Flow can not be created because socket is not connected.
|
* Flow can not be created because socket is not connected.
|
||||||
*/
|
*/
|
||||||
NOT_CONNECTED,
|
NOT_CONNECTED(NOT_CONNECTED_VALUE),
|
||||||
/**
|
/**
|
||||||
* Flow creation not supported for this socket.
|
* Flow creation not supported for this socket.
|
||||||
*/
|
*/
|
||||||
NOT_SUPPORTED,
|
NOT_SUPPORTED(NOT_SUPPORTED_VALUE),
|
||||||
/**
|
/**
|
||||||
* A flow already exists with identical attributes.
|
* A flow already exists with identical attributes.
|
||||||
*/
|
*/
|
||||||
ALREADY_CREATED,
|
ALREADY_CREATED(ALREADY_CREATED_VALUE),
|
||||||
/**
|
/**
|
||||||
* A flow is being created.
|
* A flow is being created.
|
||||||
*/
|
*/
|
||||||
IN_PROGRESS,
|
IN_PROGRESS(IN_PROGRESS_VALUE),
|
||||||
/**
|
/**
|
||||||
* Some other unspecified error.
|
* Some other unspecified error.
|
||||||
*/
|
*/
|
||||||
OTHER
|
OTHER(OTHER_VALUE);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
Status(int value) { this.value = value; }
|
||||||
|
|
||||||
|
static Status from(int value) {
|
||||||
|
if (value == NO_STATUS.value) return NO_STATUS;
|
||||||
|
else if (value == OK.value) return OK;
|
||||||
|
else if (value == NO_PERMISSION.value) return NO_PERMISSION;
|
||||||
|
else if (value == NOT_CONNECTED.value) return NOT_CONNECTED;
|
||||||
|
else if (value == NOT_SUPPORTED.value) return NOT_SUPPORTED;
|
||||||
|
else if (value == ALREADY_CREATED.value) return ALREADY_CREATED;
|
||||||
|
else if (value == IN_PROGRESS.value) return IN_PROGRESS;
|
||||||
|
else if (value == OTHER.value) return OTHER;
|
||||||
|
else throw new InternalError("Unknown value: " + value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int priority = NORMAL_PRIORITY;
|
||||||
|
private long bandwidth = UNSET;
|
||||||
|
private Status status = Status.NO_STATUS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new SocketFlow that can be used to set the SO_FLOW_SLA
|
* Creates a new SocketFlow that can be used to set the SO_FLOW_SLA
|
||||||
* socket option and create a socket flow.
|
* socket option and create a socket flow.
|
||||||
@ -111,6 +131,8 @@ public class SocketFlow {
|
|||||||
return new SocketFlow();
|
return new SocketFlow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SocketFlow() { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY
|
* Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY
|
||||||
* HIGH_PRIORITY. If not set, a flow's priority is normal.
|
* HIGH_PRIORITY. If not set, a flow's priority is normal.
|
||||||
@ -119,9 +141,8 @@ public class SocketFlow {
|
|||||||
* HIGH_PRIORITY.
|
* HIGH_PRIORITY.
|
||||||
*/
|
*/
|
||||||
public SocketFlow priority(int priority) {
|
public SocketFlow priority(int priority) {
|
||||||
if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) {
|
if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY)
|
||||||
throw new IllegalArgumentException("invalid priority");
|
throw new IllegalArgumentException("invalid priority :" + priority);
|
||||||
}
|
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -133,11 +154,9 @@ public class SocketFlow {
|
|||||||
* @throws IllegalArgumentException if bandwidth is less than zero.
|
* @throws IllegalArgumentException if bandwidth is less than zero.
|
||||||
*/
|
*/
|
||||||
public SocketFlow bandwidth(long bandwidth) {
|
public SocketFlow bandwidth(long bandwidth) {
|
||||||
if (bandwidth < 0) {
|
if (bandwidth < 0)
|
||||||
throw new IllegalArgumentException("invalid bandwidth");
|
throw new IllegalArgumentException("invalid bandwidth: " + bandwidth);
|
||||||
} else {
|
this.bandwidth = bandwidth;
|
||||||
this.bandwidth = bandwidth;
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,4 +183,18 @@ public class SocketFlow {
|
|||||||
public Status status() {
|
public Status status() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void status(int status) {
|
||||||
|
this.status = Status.from(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder(super.toString());
|
||||||
|
sb.append(" [ priority=").append(priority())
|
||||||
|
.append(", bandwidth=").append(bandwidth())
|
||||||
|
.append(", status=").append(status())
|
||||||
|
.append(" ]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
@ -27,15 +27,12 @@ package jdk.net;
|
|||||||
|
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.FileDescriptor;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.security.AccessController;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import sun.net.ExtendedOptionsImpl;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import jdk.net.ExtendedSocketOptions.PlatformSocketOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines static methods to set and get socket options defined by the
|
* Defines static methods to set and get socket options defined by the
|
||||||
@ -57,12 +54,8 @@ import sun.net.ExtendedOptionsImpl;
|
|||||||
*/
|
*/
|
||||||
public class Sockets {
|
public class Sockets {
|
||||||
|
|
||||||
private static final HashMap<Class<?>,Set<SocketOption<?>>>
|
private static final Map<Class<?>,Set<SocketOption<?>>>
|
||||||
options = new HashMap<>();
|
options = optionSets();
|
||||||
|
|
||||||
static {
|
|
||||||
initOptionSets();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Sockets() {}
|
private Sockets() {}
|
||||||
|
|
||||||
@ -259,14 +252,16 @@ public class Sockets {
|
|||||||
*/
|
*/
|
||||||
static boolean isReusePortAvailable() {
|
static boolean isReusePortAvailable() {
|
||||||
if (!checkedReusePort) {
|
if (!checkedReusePort) {
|
||||||
isReusePortAvailable = isReusePortAvailable0();
|
Set<SocketOption<?>> s = new Socket().supportedOptions();
|
||||||
|
isReusePortAvailable = s.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||||
checkedReusePort = true;
|
checkedReusePort = true;
|
||||||
}
|
}
|
||||||
return isReusePortAvailable;
|
return isReusePortAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initOptionSets() {
|
private static Map<Class<?>,Set<SocketOption<?>>> optionSets() {
|
||||||
boolean flowsupported = ExtendedOptionsImpl.flowSupported();
|
Map<Class<?>,Set<SocketOption<?>>> options = new HashMap<>();
|
||||||
|
boolean flowsupported = PlatformSocketOptions.get().flowSupported();
|
||||||
boolean reuseportsupported = isReusePortAvailable();
|
boolean reuseportsupported = isReusePortAvailable();
|
||||||
// Socket
|
// Socket
|
||||||
|
|
||||||
@ -333,7 +328,7 @@ public class Sockets {
|
|||||||
}
|
}
|
||||||
set = Collections.unmodifiableSet(set);
|
set = Collections.unmodifiableSet(set);
|
||||||
options.put(MulticastSocket.class, set);
|
options.put(MulticastSocket.class, set);
|
||||||
}
|
|
||||||
|
|
||||||
private static native boolean isReusePortAvailable0();
|
return Collections.unmodifiableMap(options);
|
||||||
|
}
|
||||||
}
|
}
|
29
jdk/src/jdk.net/share/classes/module-info.java
Normal file
29
jdk/src/jdk.net/share/classes/module-info.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jdk.net {
|
||||||
|
exports jdk.net;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 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
|
||||||
@ -23,43 +23,34 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <jni.h>
|
package jdk.net;
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "net_util.h"
|
import java.net.SocketException;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import jdk.net.ExtendedSocketOptions.PlatformSocketOptions;
|
||||||
|
|
||||||
/*
|
class SolarisSocketOptions extends PlatformSocketOptions {
|
||||||
* Class: sun_net_ExtendedOptionsImpl
|
|
||||||
* Method: init
|
public SolarisSocketOptions() { }
|
||||||
* Signature: ()V
|
|
||||||
*/
|
@Override native int setFlowOption(int fd, int priority, long bandwidth)
|
||||||
JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init
|
throws SocketException;
|
||||||
(JNIEnv *env, jclass UNUSED)
|
|
||||||
{
|
@Override native int getFlowOption(int fd, SocketFlow f)
|
||||||
}
|
throws SocketException;
|
||||||
|
|
||||||
/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */
|
@Override native boolean flowSupported();
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
|
private static native void init();
|
||||||
(JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
|
|
||||||
{
|
static {
|
||||||
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
|
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||||
"unsupported socket option");
|
public Void run() {
|
||||||
}
|
System.loadLibrary("extnet");
|
||||||
|
return null;
|
||||||
JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
|
}
|
||||||
(JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
|
});
|
||||||
{
|
init();
|
||||||
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
|
}
|
||||||
"unsupported socket option");
|
|
||||||
}
|
|
||||||
|
|
||||||
static jboolean flowSupported0() {
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported
|
|
||||||
(JNIEnv *env, jclass UNUSED)
|
|
||||||
{
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
}
|
176
jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c
Normal file
176
jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "SolarisSocketOptions.h"
|
||||||
|
|
||||||
|
static jfieldID sf_priority;
|
||||||
|
static jfieldID sf_bandwidth;
|
||||||
|
|
||||||
|
static int initialized = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: jdk_net_SolarisSocketOptions
|
||||||
|
* Method: init
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_jdk_net_SolarisSocketOptions_init
|
||||||
|
(JNIEnv *env, jclass unused)
|
||||||
|
{
|
||||||
|
if (!initialized) {
|
||||||
|
jclass c = (*env)->FindClass(env, "jdk/net/SocketFlow");
|
||||||
|
CHECK_NULL(c);
|
||||||
|
sf_priority = (*env)->GetFieldID(env, c, "priority", "I");
|
||||||
|
CHECK_NULL(sf_priority);
|
||||||
|
sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J");
|
||||||
|
CHECK_NULL(sf_bandwidth);
|
||||||
|
initialized = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the Status value. */
|
||||||
|
static jint toStatus(int errval)
|
||||||
|
{
|
||||||
|
switch (errval) {
|
||||||
|
case 0: return jdk_net_SocketFlow_OK_VALUE;
|
||||||
|
case EPERM: return jdk_net_SocketFlow_NO_PERMISSION_VALUE;
|
||||||
|
case ENOTCONN: return jdk_net_SocketFlow_NOT_CONNECTED_VALUE;
|
||||||
|
case EOPNOTSUPP: return jdk_net_SocketFlow_NOT_SUPPORTED_VALUE;
|
||||||
|
case EALREADY: return jdk_net_SocketFlow_ALREADY_CREATED_VALUE;
|
||||||
|
case EINPROGRESS: return jdk_net_SocketFlow_IN_PROGRESS_VALUE;
|
||||||
|
default: return jdk_net_SocketFlow_OTHER_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void throwByNameWithLastError
|
||||||
|
(JNIEnv *env, const char *name, const char *defaultDetail)
|
||||||
|
{
|
||||||
|
char defaultMsg[255];
|
||||||
|
sprintf(defaultMsg, "errno: %d, %s", errno, defaultDetail);
|
||||||
|
JNU_ThrowByNameWithLastError(env, name, defaultMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: jdk_net_SolarisSocketOptions
|
||||||
|
* Method: setFlowOption0
|
||||||
|
* Signature: (IIJ)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_setFlowOption
|
||||||
|
(JNIEnv *env, jobject unused, jint fd, jint priority, jlong bandwidth)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
sock_flow_props_t props;
|
||||||
|
memset(&props, 0, sizeof(props));
|
||||||
|
props.sfp_version = SOCK_FLOW_PROP_VERSION1;
|
||||||
|
|
||||||
|
if (priority != jdk_net_SocketFlow_UNSET) {
|
||||||
|
props.sfp_mask |= SFP_PRIORITY;
|
||||||
|
props.sfp_priority = priority;
|
||||||
|
}
|
||||||
|
if (bandwidth > jdk_net_SocketFlow_UNSET) {
|
||||||
|
props.sfp_mask |= SFP_MAXBW;
|
||||||
|
props.sfp_maxbw = (uint64_t) bandwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
|
||||||
|
|
||||||
|
if (rv < 0) {
|
||||||
|
if (errno == ENOPROTOOPT) {
|
||||||
|
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
|
||||||
|
"unsupported socket option");
|
||||||
|
} else if (errno == EACCES || errno == EPERM) {
|
||||||
|
JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
|
||||||
|
} else {
|
||||||
|
throwByNameWithLastError(env, "java/net/SocketException",
|
||||||
|
"set option SO_FLOW_SLA failed");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return toStatus(props.sfp_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: jdk_net_SolarisSocketOptions
|
||||||
|
* Method: getFlowOption0
|
||||||
|
* Signature: (ILjdk/net/SocketFlow;)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_getFlowOption
|
||||||
|
(JNIEnv *env, jobject unused, jint fd, jobject flow)
|
||||||
|
{
|
||||||
|
sock_flow_props_t props;
|
||||||
|
socklen_t sz = sizeof(props);
|
||||||
|
|
||||||
|
int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz);
|
||||||
|
|
||||||
|
if (rv < 0) {
|
||||||
|
if (errno == ENOPROTOOPT) {
|
||||||
|
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
|
||||||
|
"unsupported socket option");
|
||||||
|
} else if (errno == EACCES || errno == EPERM) {
|
||||||
|
JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
|
||||||
|
} else {
|
||||||
|
throwByNameWithLastError(env, "java/net/SocketException",
|
||||||
|
"get option SO_FLOW_SLA failed");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* first check status to see if flow exists */
|
||||||
|
if (props.sfp_status == 0) { /* OK */
|
||||||
|
/* can set the other fields now */
|
||||||
|
if (props.sfp_mask & SFP_PRIORITY) {
|
||||||
|
(*env)->SetIntField(env, flow, sf_priority, props.sfp_priority);
|
||||||
|
}
|
||||||
|
if (props.sfp_mask & SFP_MAXBW) {
|
||||||
|
(*env)->SetLongField(env, flow, sf_bandwidth,
|
||||||
|
(jlong)props.sfp_maxbw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toStatus(props.sfp_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_jdk_net_SolarisSocketOptions_flowSupported
|
||||||
|
(JNIEnv *env, jobject unused)
|
||||||
|
{
|
||||||
|
/* Do a simple dummy call, and try to figure out from that */
|
||||||
|
sock_flow_props_t props;
|
||||||
|
int rv, s;
|
||||||
|
|
||||||
|
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (s < 0) {
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
memset(&props, 0, sizeof(props));
|
||||||
|
props.sfp_version = SOCK_FLOW_PROP_VERSION1;
|
||||||
|
props.sfp_mask |= SFP_PRIORITY;
|
||||||
|
props.sfp_priority = SFP_PRIO_NORMAL;
|
||||||
|
rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
|
||||||
|
if (rv != 0 && errno == ENOPROTOOPT) {
|
||||||
|
rv = JNI_FALSE;
|
||||||
|
} else {
|
||||||
|
rv = JNI_TRUE;
|
||||||
|
}
|
||||||
|
close(s);
|
||||||
|
return rv;
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOLARIS_SOCKET_OPTIONS_H
|
||||||
|
#define SOLARIS_SOCKET_OPTIONS_H
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "jni_util.h"
|
||||||
|
#include "jdk_net_SocketFlow.h"
|
||||||
|
#include "SolarisSocketOptions.h"
|
||||||
|
#include "jdk_net_SolarisSocketOptions.h"
|
||||||
|
|
||||||
|
#ifndef SO_FLOW_SLA
|
||||||
|
#define SO_FLOW_SLA 0x1018
|
||||||
|
|
||||||
|
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
|
||||||
|
#pragma pack(4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used with the setsockopt(SO_FLOW_SLA, ...) call to set
|
||||||
|
* per socket service level properties.
|
||||||
|
* When the application uses per-socket API, we will enforce the properties
|
||||||
|
* on both outbound and inbound packets.
|
||||||
|
*
|
||||||
|
* For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1.
|
||||||
|
*/
|
||||||
|
typedef struct sock_flow_props_s {
|
||||||
|
int sfp_version;
|
||||||
|
uint32_t sfp_mask;
|
||||||
|
int sfp_priority; /* flow priority */
|
||||||
|
uint64_t sfp_maxbw; /* bandwidth limit in bps */
|
||||||
|
int sfp_status; /* flow create status for getsockopt */
|
||||||
|
} sock_flow_props_t;
|
||||||
|
|
||||||
|
#define SOCK_FLOW_PROP_VERSION1 1
|
||||||
|
|
||||||
|
/* bit mask values for sfp_mask */
|
||||||
|
#define SFP_MAXBW 0x00000001 /* Flow Bandwidth Limit */
|
||||||
|
#define SFP_PRIORITY 0x00000008 /* Flow priority */
|
||||||
|
|
||||||
|
/* possible values for sfp_priority */
|
||||||
|
#define SFP_PRIO_NORMAL 1
|
||||||
|
#define SFP_PRIO_HIGH 2
|
||||||
|
|
||||||
|
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
|
||||||
|
#pragma pack()
|
||||||
|
#endif /* _LONG_LONG_ALIGNMENT */
|
||||||
|
|
||||||
|
#endif /* SO_FLOW_SLA */
|
||||||
|
|
||||||
|
#endif /* SOLARIS_SOCKET_OPTIONS_H */
|
@ -28,6 +28,7 @@ module jdk.policytool {
|
|||||||
requires java.logging;
|
requires java.logging;
|
||||||
requires java.management;
|
requires java.management;
|
||||||
requires java.sql;
|
requires java.sql;
|
||||||
|
requires jdk.net;
|
||||||
requires java.security.jgss;
|
requires java.security.jgss;
|
||||||
requires jdk.security.jgss;
|
requires jdk.security.jgss;
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,13 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8036979 8072384
|
* @bug 8036979 8072384 8044773
|
||||||
* @run main/othervm -Xcheck:jni OptionsTest
|
* @run main/othervm -Xcheck:jni OptionsTest
|
||||||
* @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest
|
* @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest
|
||||||
|
* @run main/othervm -Djdk.launcher.limitmods=java.base OptionsTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ public class OptionsTest {
|
|||||||
}
|
}
|
||||||
Object option;
|
Object option;
|
||||||
Object testValue;
|
Object testValue;
|
||||||
};
|
}
|
||||||
|
|
||||||
// The tests set the option using the new API, read back the set value
|
// The tests set the option using the new API, read back the set value
|
||||||
// which could be diferent, and then use the legacy get API to check
|
// which could be diferent, and then use the legacy get API to check
|
||||||
@ -223,8 +225,7 @@ public class OptionsTest {
|
|||||||
} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
|
} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
|
||||||
return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
|
return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
|
||||||
} else if (option.equals(StandardSocketOptions.IP_TOS)) {
|
} else if (option.equals(StandardSocketOptions.IP_TOS)) {
|
||||||
return Integer.valueOf(jdk.net.Sockets.getOption(
|
return getServerSocketTrafficClass(socket);
|
||||||
socket, StandardSocketOptions.IP_TOS));
|
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("unexecpted socket option");
|
throw new RuntimeException("unexecpted socket option");
|
||||||
}
|
}
|
||||||
@ -281,4 +282,20 @@ public class OptionsTest {
|
|||||||
doDgSocketTests();
|
doDgSocketTests();
|
||||||
doMcSocketTests();
|
doMcSocketTests();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reflectively access jdk.net.Sockets.getOption so that the test can run
|
||||||
|
// without the jdk.net module.
|
||||||
|
static Object getServerSocketTrafficClass(ServerSocket ss) throws Exception {
|
||||||
|
try {
|
||||||
|
Class<?> c = Class.forName("jdk.net.Sockets");
|
||||||
|
Method m = c.getDeclaredMethod("getOption", ServerSocket.class, SocketOption.class);
|
||||||
|
return m.invoke(null, ss, StandardSocketOptions.IP_TOS);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// Ok, jdk.net module not present, just fall back
|
||||||
|
System.out.println("jdk.net module not present, falling back.");
|
||||||
|
return Integer.valueOf(ss.getOption(StandardSocketOptions.IP_TOS));
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,34 +21,48 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import jdk.net.ExtendedSocketOptions;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8143554
|
* @bug 8143554 8044773
|
||||||
* @run main UnsupportedOptionsTest
|
|
||||||
* @summary Test checks that UnsupportedOperationException for unsupported
|
* @summary Test checks that UnsupportedOperationException for unsupported
|
||||||
* SOCKET_OPTIONS is thrown by both getOption() and setOption() methods.
|
* SOCKET_OPTIONS is thrown by both getOption() and setOption() methods.
|
||||||
|
* @run main UnsupportedOptionsTest
|
||||||
|
* @run main/othervm -Djdk.launcher.limitmods=java.base UnsupportedOptionsTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class UnsupportedOptionsTest {
|
public class UnsupportedOptionsTest {
|
||||||
|
|
||||||
private static final SocketOption[] SOCKET_OPTIONS = {
|
private static final List<SocketOption<?>> socketOptions = new ArrayList<>();
|
||||||
StandardSocketOptions.IP_MULTICAST_IF,
|
|
||||||
StandardSocketOptions.IP_MULTICAST_LOOP,
|
static {
|
||||||
StandardSocketOptions.IP_MULTICAST_TTL,
|
socketOptions.add(StandardSocketOptions.IP_MULTICAST_IF);
|
||||||
StandardSocketOptions.IP_TOS,
|
socketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP);
|
||||||
StandardSocketOptions.SO_BROADCAST,
|
socketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL);
|
||||||
StandardSocketOptions.SO_KEEPALIVE,
|
socketOptions.add(StandardSocketOptions.IP_TOS);
|
||||||
StandardSocketOptions.SO_LINGER,
|
socketOptions.add(StandardSocketOptions.SO_BROADCAST);
|
||||||
StandardSocketOptions.SO_RCVBUF,
|
socketOptions.add(StandardSocketOptions.SO_KEEPALIVE);
|
||||||
StandardSocketOptions.SO_REUSEADDR,
|
socketOptions.add(StandardSocketOptions.SO_LINGER);
|
||||||
StandardSocketOptions.SO_SNDBUF,
|
socketOptions.add(StandardSocketOptions.SO_RCVBUF);
|
||||||
StandardSocketOptions.TCP_NODELAY,
|
socketOptions.add(StandardSocketOptions.SO_REUSEADDR);
|
||||||
ExtendedSocketOptions.SO_FLOW_SLA
|
socketOptions.add(StandardSocketOptions.SO_SNDBUF);
|
||||||
};
|
socketOptions.add(StandardSocketOptions.TCP_NODELAY);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> c = Class.forName("jdk.net.ExtendedSocketOptions");
|
||||||
|
Field field = c.getField("SO_FLOW_SLA");
|
||||||
|
socketOptions.add((SocketOption<?>)field.get(null));
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// ignore, jdk.net module not present
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
Socket s = new Socket();
|
Socket s = new Socket();
|
||||||
@ -56,7 +70,7 @@ public class UnsupportedOptionsTest {
|
|||||||
DatagramSocket ds = new DatagramSocket();
|
DatagramSocket ds = new DatagramSocket();
|
||||||
MulticastSocket ms = new MulticastSocket();
|
MulticastSocket ms = new MulticastSocket();
|
||||||
|
|
||||||
for (SocketOption option : SOCKET_OPTIONS) {
|
for (SocketOption option : socketOptions) {
|
||||||
if (!s.supportedOptions().contains(option)) {
|
if (!s.supportedOptions().contains(option)) {
|
||||||
testUnsupportedSocketOption(s, option);
|
testUnsupportedSocketOption(s, option);
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4640544
|
* @bug 4640544 8044773
|
||||||
* @summary Unit test for setOption/getOption/options methods
|
* @summary Unit test for setOption/getOption/options methods
|
||||||
|
* @run main SocketOptionTests
|
||||||
|
* @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
|
@ -22,9 +22,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4640544
|
* @bug 4640544 8044773
|
||||||
* @summary Unit test for ServerSocketChannel setOption/getOption/options
|
* @summary Unit test for ServerSocketChannel setOption/getOption/options
|
||||||
* methods.
|
* methods.
|
||||||
|
* @run main SocketOptionTests
|
||||||
|
* @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
|
@ -22,9 +22,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4640544
|
* @bug 4640544 8044773
|
||||||
* @summary Unit test to check SocketChannel setOption/getOption/options
|
* @summary Unit test to check SocketChannel setOption/getOption/options
|
||||||
* methods.
|
* methods.
|
||||||
|
* @run main SocketOptionTests
|
||||||
|
* @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
|
93
jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java
Normal file
93
jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8765432
|
||||||
|
* @summary Basic test for SocketFlow API
|
||||||
|
* @run testng SocketFlowBasic
|
||||||
|
*/
|
||||||
|
|
||||||
|
import jdk.net.SocketFlow;
|
||||||
|
import org.testng.annotations.DataProvider;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
import static jdk.net.SocketFlow.*;
|
||||||
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
|
public class SocketFlowBasic {
|
||||||
|
|
||||||
|
@DataProvider
|
||||||
|
public Object[][] validPriorities() {
|
||||||
|
return new Object[][] { {HIGH_PRIORITY}, {NORMAL_PRIORITY} };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "validPriorities")
|
||||||
|
public void priority(long validPriority) {
|
||||||
|
SocketFlow flow = SocketFlow.create();
|
||||||
|
flow.bandwidth(validPriority);
|
||||||
|
long bandwidth = flow.bandwidth();
|
||||||
|
assertTrue(bandwidth == validPriority, "Expected " + validPriority + ", got" + bandwidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider
|
||||||
|
public Object[][] invalidPriorities() {
|
||||||
|
return new Object[][] { {HIGH_PRIORITY+10}, {NORMAL_PRIORITY-10000} };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "invalidPriorities", expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void priority(int invalidPriority) {
|
||||||
|
SocketFlow flow = SocketFlow.create();
|
||||||
|
flow.priority(invalidPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider
|
||||||
|
public Object[][] positiveBandwidth() {
|
||||||
|
return new Object[][] { {0}, {100}, {Integer.MAX_VALUE}, {Long.MAX_VALUE} };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "positiveBandwidth")
|
||||||
|
public void bandwidth(long posBandwidth) {
|
||||||
|
SocketFlow flow = SocketFlow.create();
|
||||||
|
flow.bandwidth(posBandwidth);
|
||||||
|
long bandwidth = flow.bandwidth();
|
||||||
|
assertTrue(bandwidth == posBandwidth, "Expected " + posBandwidth + ", got" + bandwidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@DataProvider
|
||||||
|
public Object[][] negativeBandwidth() {
|
||||||
|
return new Object[][] { {-1}, {-100}, {Integer.MIN_VALUE}, {Long.MIN_VALUE} };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "negativeBandwidth", expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void invalidBandwidth(long negBandwidth) {
|
||||||
|
SocketFlow flow = SocketFlow.create();
|
||||||
|
flow.bandwidth(negBandwidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void status() {
|
||||||
|
SocketFlow flow = SocketFlow.create();
|
||||||
|
assertTrue(flow.status() == Status.NO_STATUS);
|
||||||
|
}
|
||||||
|
}
|
@ -23,8 +23,9 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8032808
|
* @bug 8032808 8044773
|
||||||
* @run main/othervm -Xcheck:jni Test
|
* @modules jdk.net
|
||||||
|
* @run main/othervm -Xcheck:jni Test success
|
||||||
* @run main/othervm/policy=policy.fail -Xcheck:jni Test fail
|
* @run main/othervm/policy=policy.fail -Xcheck:jni Test fail
|
||||||
* @run main/othervm/policy=policy.success -Xcheck:jni Test success
|
* @run main/othervm/policy=policy.success -Xcheck:jni Test success
|
||||||
*/
|
*/
|
||||||
@ -35,15 +36,13 @@ import java.nio.channels.*;
|
|||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import jdk.net.*;
|
import jdk.net.*;
|
||||||
|
import static java.lang.System.out;
|
||||||
|
|
||||||
public class Test {
|
public class Test {
|
||||||
|
|
||||||
static boolean security;
|
interface Runner { void run() throws Exception; }
|
||||||
static boolean success;
|
|
||||||
|
|
||||||
interface Runner {
|
static boolean expectSuccess;
|
||||||
public void run() throws Exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
@ -52,95 +51,107 @@ public class Test {
|
|||||||
|
|
||||||
Sockets.supportedOptions(Socket.class);
|
Sockets.supportedOptions(Socket.class);
|
||||||
|
|
||||||
security = System.getSecurityManager() != null;
|
expectSuccess = args[0].equals("success");
|
||||||
success = security && args[0].equals("success");
|
|
||||||
|
|
||||||
// Main thing is to check for JNI problems
|
// Main thing is to check for JNI problems
|
||||||
// Doesn't matter if current system does not support the option
|
// Doesn't matter if current system does not support the option
|
||||||
// and currently setting the option with the loopback interface
|
// and currently setting the option with the loopback interface
|
||||||
// doesn't work either
|
// doesn't work either
|
||||||
|
|
||||||
System.out.println ("Security Manager enabled: " + security);
|
boolean sm = System.getSecurityManager() != null;
|
||||||
if (security) {
|
out.println("Security Manager enabled: " + sm);
|
||||||
System.out.println ("Success expected: " + success);
|
out.println("Success expected: " + expectSuccess);
|
||||||
|
|
||||||
|
SocketFlow flowIn = SocketFlow.create()
|
||||||
|
.bandwidth(1000)
|
||||||
|
.priority(SocketFlow.HIGH_PRIORITY);
|
||||||
|
|
||||||
|
try (ServerSocket ss = new ServerSocket(0);
|
||||||
|
DatagramSocket dg = new DatagramSocket(0)) {
|
||||||
|
|
||||||
|
int tcp_port = ss.getLocalPort();
|
||||||
|
final InetAddress loop = InetAddress.getByName("127.0.0.1");
|
||||||
|
final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port);
|
||||||
|
|
||||||
|
final int udp_port = dg.getLocalPort();
|
||||||
|
|
||||||
|
// If option not available, end test
|
||||||
|
Set<SocketOption<?>> options = dg.supportedOptions();
|
||||||
|
if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) {
|
||||||
|
System.out.println("SO_FLOW_SLA not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Socket s = new Socket("127.0.0.1", tcp_port);
|
||||||
|
final SocketChannel sc = SocketChannel.open();
|
||||||
|
sc.connect(new InetSocketAddress("127.0.0.1", tcp_port));
|
||||||
|
|
||||||
|
doTest("Sockets.setOption Socket", () -> {
|
||||||
|
out.println(flowIn);
|
||||||
|
Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
||||||
|
out.println(flowIn);
|
||||||
|
});
|
||||||
|
doTest("Sockets.getOption Socket",() -> {
|
||||||
|
Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA);
|
||||||
|
out.println(flowIn);
|
||||||
|
});
|
||||||
|
doTest("Sockets.setOption SocketChannel",() ->
|
||||||
|
sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn)
|
||||||
|
);
|
||||||
|
doTest("Sockets.getOption SocketChannel",() ->
|
||||||
|
sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA)
|
||||||
|
);
|
||||||
|
doTest("Sockets.setOption DatagramSocket",() -> {
|
||||||
|
try (DatagramSocket dg1 = new DatagramSocket(0)) {
|
||||||
|
dg1.connect(loop, udp_port);
|
||||||
|
Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
doTest("Sockets.setOption DatagramSocket 2", () -> {
|
||||||
|
try (DatagramChannel dg2 = DatagramChannel.open()) {
|
||||||
|
dg2.bind(new InetSocketAddress(loop, 0));
|
||||||
|
dg2.connect(new InetSocketAddress(loop, udp_port));
|
||||||
|
dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
doTest("Sockets.setOption MulticastSocket", () -> {
|
||||||
|
try (MulticastSocket mc1 = new MulticastSocket(0)) {
|
||||||
|
mc1.connect(loop, udp_port);
|
||||||
|
Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
doTest("Sockets.setOption AsynchronousSocketChannel", () -> {
|
||||||
|
try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) {
|
||||||
|
Future<Void> f = asc.connect(loopad);
|
||||||
|
f.get();
|
||||||
|
asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
final SocketFlow flowIn = SocketFlow.create()
|
|
||||||
.bandwidth(1000)
|
|
||||||
.priority(SocketFlow.HIGH_PRIORITY);
|
|
||||||
|
|
||||||
ServerSocket ss = new ServerSocket(0);
|
|
||||||
int tcp_port = ss.getLocalPort();
|
|
||||||
final InetAddress loop = InetAddress.getByName("127.0.0.1");
|
|
||||||
final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port);
|
|
||||||
|
|
||||||
DatagramSocket dg = new DatagramSocket(0);
|
|
||||||
final int udp_port = dg.getLocalPort();
|
|
||||||
|
|
||||||
// If option not available, end test
|
|
||||||
Set<SocketOption<?>> options = dg.supportedOptions();
|
|
||||||
if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) {
|
|
||||||
System.out.println("SO_FLOW_SLA not supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Socket s = new Socket("127.0.0.1", tcp_port);
|
|
||||||
final SocketChannel sc = SocketChannel.open();
|
|
||||||
sc.connect (new InetSocketAddress("127.0.0.1", tcp_port));
|
|
||||||
|
|
||||||
doTest(()->{
|
|
||||||
Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
|
||||||
});
|
|
||||||
doTest(()->{
|
|
||||||
Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA);
|
|
||||||
});
|
|
||||||
doTest(()->{
|
|
||||||
sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
|
||||||
});
|
|
||||||
doTest(()->{
|
|
||||||
sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA);
|
|
||||||
});
|
|
||||||
doTest(()->{
|
|
||||||
DatagramSocket dg1 = new DatagramSocket(0);
|
|
||||||
dg1.connect(loop, udp_port);
|
|
||||||
Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
|
||||||
});
|
|
||||||
doTest(()->{
|
|
||||||
DatagramChannel dg2 = DatagramChannel.open();
|
|
||||||
dg2.bind(new InetSocketAddress(loop, 0));
|
|
||||||
dg2.connect(new InetSocketAddress(loop, udp_port));
|
|
||||||
dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
|
||||||
});
|
|
||||||
doTest(()->{
|
|
||||||
MulticastSocket mc1 = new MulticastSocket(0);
|
|
||||||
mc1.connect(loop, udp_port);
|
|
||||||
Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
|
||||||
});
|
|
||||||
doTest(()->{
|
|
||||||
AsynchronousSocketChannel asc = AsynchronousSocketChannel.open();
|
|
||||||
Future<Void> f = asc.connect(loopad);
|
|
||||||
f.get();
|
|
||||||
asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void doTest(Runner func) throws Exception {
|
static void doTest(String message, Runner func) throws Exception {
|
||||||
|
out.println(message);
|
||||||
try {
|
try {
|
||||||
func.run();
|
func.run();
|
||||||
if (security && !success) {
|
if (expectSuccess) {
|
||||||
throw new RuntimeException("Test failed");
|
out.println("Completed as expected");
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Operation succeeded, but expected SecurityException");
|
||||||
}
|
}
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
if (success) {
|
if (expectSuccess) {
|
||||||
throw new RuntimeException("Test failed");
|
throw new RuntimeException("Unexpected SecurityException", e);
|
||||||
|
} else {
|
||||||
|
out.println("Caught expected: " + e);
|
||||||
}
|
}
|
||||||
} catch (UnsupportedOperationException e) {
|
} catch (UnsupportedOperationException e) {
|
||||||
System.out.println (e);
|
System.out.println(e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// Probably a permission error, but we're not
|
// Probably a permission error, but we're not
|
||||||
// going to check unless a specific permission exception
|
// going to check unless a specific permission exception
|
||||||
// is defined.
|
// is defined.
|
||||||
System.out.println (e);
|
System.out.println(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user