Mercurial > hg > icedtea7-forest-aarch64 > jdk
changeset 7912:f40d035e338d
8032808: Support Solaris SO_FLOW_SLA socket option
Reviewed-by: michaelm
line wrap: on
line diff
--- a/make/Makefile Tue Aug 26 15:55:35 2014 +0400 +++ b/make/Makefile Fri Aug 22 16:10:50 2014 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1995, 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 @@ -232,7 +232,7 @@ all build:: sanity-all post-sanity-all -SUBDIRS = tools java javax sun com +SUBDIRS = tools java javax jdk sun com ifeq ($(PLATFORM), macosx) SUBDIRS += apple endif
--- a/make/common/shared/Defs-javadoc.gmk Tue Aug 26 15:55:35 2014 +0400 +++ b/make/common/shared/Defs-javadoc.gmk Fri Aug 22 16:10:50 2014 +0100 @@ -43,6 +43,7 @@ TREEAPI_FIRST_COPYRIGHT_YEAR = 2005 JNLP_FIRST_COPYRIGHT_YEAR = 1998 PLUGIN2_FIRST_COPYRIGHT_YEAR = 2007 +JDKNET_FIRST_COPYRIGHT_YEAR = 2014 # Oracle name FULL_COMPANY_NAME = Oracle and/or its affiliates
--- a/make/docs/Makefile Tue Aug 26 15:55:35 2014 +0400 +++ b/make/docs/Makefile Fri Aug 22 16:10:50 2014 +0100 @@ -1,4 +1,4 @@ -# Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 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 @@ -836,6 +836,56 @@ ############################################################# # +# jdk.net docs +# + +ALL_OTHER_TARGETS += jdknetdocs + +JDKNET_DOCDIR := $(JRE_API_DOCSDIR)/net/socketoptions/spec +JDKNET2COREAPI := ../../../$(JDKJRE2COREAPI) +JDKNET_DOCTITLE := jdk.net API +JDKNET_WINDOWTITLE := jdk.net API +JDKNET_HEADER := <strong>jdk.net API</strong> +JDKNET_BOTTOM := $(call CommonBottom,$(JDKNET_FIRST_COPYRIGHT_YEAR)) +# JDKNET_PKGS is located in NON_CORE_PKGS.gmk + +JDKNET_INDEX_HTML = $(JDKNET_DOCDIR)/index.html +JDKNET_OPTIONS_FILE = $(DOCSTMPDIR)/jdknet.options +JDKNET_PACKAGES_FILE = $(DOCSTMPDIR)/jdknet.packages + +jdknetdocs: $(JDKNET_INDEX_HTML) + +# Set relative location to core api document root +$(JDKNET_INDEX_HTML): GET2DOCSDIR=$(JDKNET2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(JDKNET_INDEX_HTML): $(JDKNET_OPTIONS_FILE) $(JDKNET_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(JDKNET_OPTIONS_FILE),$(JDKNET_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(JDKNET_OPTIONS_FILE) @$(JDKNET_PACKAGES_FILE) + +# Create file with javadoc options in it +$(JDKNET_OPTIONS_FILE): + $(prep-target) + @($(call OptionOnly,$(COMMON_JAVADOCFLAGS)) ; \ + $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \ + $(call OptionPair,-encoding,ascii) ; \ + $(call OptionOnly,-nodeprecatedlist) ; \ + $(call OptionPair,-doctitle,$(JDKNET_DOCTITLE)) ; \ + $(call OptionPair,-windowtitle,$(JDKNET_WINDOWTITLE) $(DRAFT_WINTITLE));\ + $(call OptionPair,-header,$(JDKNET_HEADER)$(DRAFT_HEADER)); \ + $(call OptionPair,-bottom,$(JDKNET_BOTTOM)$(DRAFT_BOTTOM)); \ + $(call OptionTrip,-linkoffline,$(JDKNET2COREAPI),$(COREAPI_DOCSDIR)/); \ + ) >> $@ + +# Create a file with the package names in it +$(JDKNET_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JDKNET_PKGS)) + $(prep-target) + $(call PackageFilter,$(JDKNET_PKGS)) + +############################################################# +# # httpserverdocs #
--- a/make/docs/NON_CORE_PKGS.gmk Tue Aug 26 15:55:35 2014 +0400 +++ b/make/docs/NON_CORE_PKGS.gmk Fri Aug 22 16:10:50 2014 +0100 @@ -62,6 +62,8 @@ OLD_JSSE_PKGS = com.sun.net.ssl +JDKNET_PKGS = jdk.net + HTTPSERVER_PKGS = com.sun.net.httpserver \ com.sun.net.httpserver.spi @@ -99,6 +101,7 @@ NON_CORE_PKGS = $(DOMAPI_PKGS) \ $(MGMT_PKGS) \ $(JAAS_PKGS) \ + $(JDKNET_PKGS) \ $(JGSS_PKGS) \ $(NIO_PKGS) \ $(OLD_JSSE_PKGS) \
--- a/make/java/net/FILES_c.gmk Tue Aug 26 15:55:35 2014 +0400 +++ b/make/java/net/FILES_c.gmk Fri Aug 22 16:10:50 2014 +0100 @@ -25,6 +25,7 @@ FILES_c = \ DatagramPacket.c \ + ExtendedOptionsImpl.c \ InetAddress.c \ Inet4Address.c \ Inet6Address.c \
--- a/make/java/net/mapfile-vers Tue Aug 26 15:55:35 2014 +0400 +++ b/make/java/net/mapfile-vers Fri Aug 22 16:10:50 2014 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 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 @@ -94,6 +94,10 @@ Java_sun_net_sdp_SdpSupport_create0; Java_sun_net_spi_DefaultProxySelector_init; 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_SockaddrToInetAddress; NET_SockaddrEqualsInetAddress;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/jdk/Makefile Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,40 @@ +# +# 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. +# + +# +# Makefile for building jdk sub dir +# + +BUILDDIR = .. +PRODUCT = jdk +include $(BUILDDIR)/common/Defs.gmk + +SUBDIRS = net + +include $(BUILDDIR)/common/Subdirs.gmk + +all build clean clobber:: + $(SUBDIRS-loop) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/jdk/net/FILES_java.gmk Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,30 @@ +# +# 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. +# + +FILES_java = \ + jdk/net/ExtendedSocketOptions.java \ + jdk/net/NetworkPermission.java \ + jdk/net/SocketFlow.java \ + jdk/net/Sockets.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/jdk/net/Makefile Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,43 @@ +# +# 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. +# + +# +# Makefile for building jdk.net classes +# + +BUILDDIR = ../.. +PACKAGE = jdk.net +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +# +# Files to compile. +# +AUTO_FILES_JAVA_DIRS = jdk/net + +# +# Rules. +# +include $(BUILDDIR)/common/Classes.gmk
--- a/make/sun/net/FILES_java.gmk Tue Aug 26 15:55:35 2014 +0400 +++ b/make/sun/net/FILES_java.gmk Fri Aug 22 16:10:50 2014 +0100 @@ -24,6 +24,7 @@ # FILES_java = \ + sun/net/ExtendedOptionsImpl.java \ sun/net/InetAddressCachePolicy.java \ sun/net/URLCanonicalizer.java \ sun/net/NetworkClient.java \
--- a/src/share/classes/java/net/DatagramSocket.java Tue Aug 26 15:55:35 2014 +0400 +++ b/src/share/classes/java/net/DatagramSocket.java Fri Aug 22 16:10:50 2014 +0100 @@ -320,6 +320,7 @@ } // creates a udp socket impl.create(); + impl.setDatagramSocket(this); created = true; }
--- a/src/share/classes/java/net/DatagramSocketImpl.java Tue Aug 26 15:55:35 2014 +0400 +++ b/src/share/classes/java/net/DatagramSocketImpl.java Fri Aug 22 16:10:50 2014 +0100 @@ -48,6 +48,20 @@ protected FileDescriptor fd; /** + * The DatagramSocket or MulticastSocket + * that owns this impl + */ + DatagramSocket socket; + + void setDatagramSocket(DatagramSocket socket) { + this.socket = socket; + } + + DatagramSocket getDatagramSocket() { + return socket; + } + + /** * Creates a datagram socket. * @exception SocketException if there is an error in the * underlying protocol, such as a TCP error. @@ -233,6 +247,56 @@ return localPort; } + <T> void setOption(SocketOption<T> name, T value) throws IOException { + if (name == StandardSocketOptions.SO_SNDBUF) { + setOption(SocketOptions.SO_SNDBUF, value); + } else if (name == StandardSocketOptions.SO_RCVBUF) { + setOption(SocketOptions.SO_RCVBUF, value); + } else if (name == StandardSocketOptions.SO_REUSEADDR) { + setOption(SocketOptions.SO_REUSEADDR, value); + } else if (name == StandardSocketOptions.IP_TOS) { + setOption(SocketOptions.IP_TOS, value); + } else if (name == StandardSocketOptions.IP_MULTICAST_IF && + (getDatagramSocket() instanceof MulticastSocket)) { + setOption(SocketOptions.IP_MULTICAST_IF2, value); + } else if (name == StandardSocketOptions.IP_MULTICAST_TTL && + (getDatagramSocket() instanceof MulticastSocket)) { + if (! (value instanceof Integer)) { + throw new IllegalArgumentException("not an integer"); + } + setTimeToLive((Integer)value); + } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP && + (getDatagramSocket() instanceof MulticastSocket)) { + setOption(SocketOptions.IP_MULTICAST_LOOP, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } + + <T> T getOption(SocketOption<T> name) throws IOException { + if (name == StandardSocketOptions.SO_SNDBUF) { + return (T) getOption(SocketOptions.SO_SNDBUF); + } else if (name == StandardSocketOptions.SO_RCVBUF) { + return (T) getOption(SocketOptions.SO_RCVBUF); + } else if (name == StandardSocketOptions.SO_REUSEADDR) { + return (T) getOption(SocketOptions.SO_REUSEADDR); + } else if (name == StandardSocketOptions.IP_TOS) { + return (T) getOption(SocketOptions.IP_TOS); + } else if (name == StandardSocketOptions.IP_MULTICAST_IF && + (getDatagramSocket() instanceof MulticastSocket)) { + return (T) getOption(SocketOptions.IP_MULTICAST_IF2); + } else if (name == StandardSocketOptions.IP_MULTICAST_TTL && + (getDatagramSocket() instanceof MulticastSocket)) { + Integer ttl = getTimeToLive(); + return (T)ttl; + } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP && + (getDatagramSocket() instanceof MulticastSocket)) { + return (T) getOption(SocketOptions.IP_MULTICAST_LOOP); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } + /** * Gets the datagram socket file descriptor. * @return a <tt>FileDescriptor</tt> object representing the datagram socket
--- a/src/share/classes/java/net/SocketImpl.java Tue Aug 26 15:55:35 2014 +0400 +++ b/src/share/classes/java/net/SocketImpl.java Fri Aug 22 16:10:50 2014 +0100 @@ -354,4 +354,44 @@ { /* Not implemented yet */ } + + <T> void setOption(SocketOption<T> name, T value) throws IOException { + if (name == StandardSocketOptions.SO_KEEPALIVE) { + setOption(SocketOptions.SO_KEEPALIVE, value); + } else if (name == StandardSocketOptions.SO_SNDBUF) { + setOption(SocketOptions.SO_SNDBUF, value); + } else if (name == StandardSocketOptions.SO_RCVBUF) { + setOption(SocketOptions.SO_RCVBUF, value); + } else if (name == StandardSocketOptions.SO_REUSEADDR) { + setOption(SocketOptions.SO_REUSEADDR, value); + } else if (name == StandardSocketOptions.SO_LINGER) { + setOption(SocketOptions.SO_LINGER, value); + } else if (name == StandardSocketOptions.IP_TOS) { + setOption(SocketOptions.IP_TOS, value); + } else if (name == StandardSocketOptions.TCP_NODELAY) { + setOption(SocketOptions.TCP_NODELAY, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } + + <T> T getOption(SocketOption<T> name) throws IOException { + if (name == StandardSocketOptions.SO_KEEPALIVE) { + return (T)getOption(SocketOptions.SO_KEEPALIVE); + } else if (name == StandardSocketOptions.SO_SNDBUF) { + return (T)getOption(SocketOptions.SO_SNDBUF); + } else if (name == StandardSocketOptions.SO_RCVBUF) { + return (T)getOption(SocketOptions.SO_RCVBUF); + } else if (name == StandardSocketOptions.SO_REUSEADDR) { + return (T)getOption(SocketOptions.SO_REUSEADDR); + } else if (name == StandardSocketOptions.SO_LINGER) { + return (T)getOption(SocketOptions.SO_LINGER); + } else if (name == StandardSocketOptions.IP_TOS) { + return (T)getOption(SocketOptions.IP_TOS); + } else if (name == StandardSocketOptions.TCP_NODELAY) { + return (T)getOption(SocketOptions.TCP_NODELAY); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/net/SocketSecrets.java Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,70 @@ +/* + * 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 java.net; + +import java.io.IOException; + +class SocketSecrets { + + /* accessed by reflection from jdk.net.Sockets */ + + /* obj must be a Socket or ServerSocket */ + + private static <T> void setOption(Object obj, SocketOption<T> name, T value) throws IOException { + SocketImpl impl; + + if (obj instanceof Socket) { + impl = ((Socket)obj).getImpl(); + } else if (obj instanceof ServerSocket) { + impl = ((ServerSocket)obj).getImpl(); + } else { + throw new IllegalArgumentException(); + } + impl.setOption(name, value); + } + + private static <T> T getOption(Object obj, SocketOption<T> name) throws IOException { + SocketImpl impl; + + if (obj instanceof Socket) { + impl = ((Socket)obj).getImpl(); + } else if (obj instanceof ServerSocket) { + impl = ((ServerSocket)obj).getImpl(); + } else { + throw new IllegalArgumentException(); + } + return impl.getOption(name); + } + + private static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException { + s.getImpl().setOption(name, value); + } + + private static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException { + return s.getImpl().getOption(name); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/jdk/net/ExtendedSocketOptions.java Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,60 @@ +/* + * 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. + * + */ +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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/jdk/net/NetworkPermission.java Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,89 @@ +/* + * 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.security.BasicPermission; + +/** + * Represents permission to access the extended networking capabilities + * defined in the jdk.net package. These permissions contain a target + * name, but no actions list. Callers either possess the permission or not. + * <p> + * The following targets are defined: + * <p> + * <table border=1 cellpadding=5 summary="permission target name, + * what the target allows,and associated risks"> + * <tr> + * <th>Permission Target Name</th> + * <th>What the Permission Allows</th> + * <th>Risks of Allowing this Permission</th> + * </tr> + * <tr> + * <td>setOption.SO_FLOW_SLA</td> + * <td>set the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} option + * on any socket that supports it</td> + * <td>allows caller to set a higher priority or bandwidth allocation + * to sockets it creates, than they might otherwise be allowed.</td> + * </tr> + * <tr> + * <td>getOption.SO_FLOW_SLA</td> + * <td>retrieve the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} + * setting from any socket that supports the option</td> + * <td>allows caller access to SLA information that it might not + * otherwise have</td> + * </tr></table> + * + * @see jdk.net.ExtendedSocketOptions + * + */ + +public final class NetworkPermission extends BasicPermission { + + private static final long serialVersionUID = -2012939586906722291L; + + /** + * Creates a NetworkPermission with the given target name. + * + * @param name the permission target name + * @throws NullPointerException if {@code name} is {@code null}. + * @throws IllegalArgumentException if {@code name} is empty. + */ + public NetworkPermission(String name) { + super(name); + } + + /** + * Creates a NetworkPermission with the given target name. + * + * @param name the permission target name + * @param actions should be {@code null}. Is ignored if not. + * @throws NullPointerException if {@code name} is {@code null}. + * @throws IllegalArgumentException if {@code name} is empty. + */ + public NetworkPermission(String name, String actions) { + super(name, actions); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/jdk/net/SocketFlow.java Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,165 @@ +/* + * 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; + + +/** + * Represents the service level properties for the platform specific socket + * option {@link ExtendedSocketOptions#SO_FLOW_SLA}. + * <p> + * The priority and bandwidth parameters must be set before + * setting the socket option. + * <p> + * When the {@code SO_FLOW_SLA} option is set then it may not take effect + * immediately. If the value of the socket option is obtained with + * {@code getOption()} then the status may be returned as {@code INPROGRESS} + * until it takes effect. The priority and bandwidth values are only valid when + * the status is returned as OK. + * <p> + * When a security manager is installed, a {@link NetworkPermission} + * is required to set or get this option. + * + */ + +public class SocketFlow { + + private static final int UNSET = -1; + public static final int NORMAL_PRIORITY = 1; + public static final int HIGH_PRIORITY = 2; + + private int priority = NORMAL_PRIORITY; + + private long bandwidth = UNSET; + + private Status status = Status.NO_STATUS; + + private SocketFlow() {} + + /** + * Enumeration of the return values from the SO_FLOW_SLA + * socket option. Both setting and getting the option return + * one of these statuses, which reflect the state of socket's + * flow. + * + */ + public enum Status { + /** + * Set or get socket option has not been called yet. Status + * values can only be retrieved after calling set or get. + */ + NO_STATUS, + /** + * Flow successfully created. + */ + OK, + /** + * Caller has no permission to create flow. + */ + NO_PERMISSION, + /** + * Flow can not be created because socket is not connected. + */ + NOT_CONNECTED, + /** + * Flow creation not supported for this socket. + */ + NOT_SUPPORTED, + /** + * A flow already exists with identical attributes. + */ + ALREADY_CREATED, + /** + * A flow is being created. + */ + IN_PROGRESS, + /** + * Some other unspecified error. + */ + OTHER + } + + /** + * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA + * socket option and create a socket flow. + */ + public static SocketFlow create() { + return new SocketFlow(); + } + + /** + * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY + * HIGH_PRIORITY. If not set, a flow's priority is normal. + * + * @throws IllegalArgumentException if priority is not NORMAL_PRIORITY or + * HIGH_PRIORITY. + */ + public SocketFlow priority(int priority) { + if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) { + throw new IllegalArgumentException("invalid priority"); + } + this.priority = priority; + return this; + } + + /** + * Sets this SocketFlow's bandwidth. Must be greater than or equal to zero. + * A value of zero drops all packets for the socket. + * + * @throws IllegalArgumentException if bandwidth is less than zero. + */ + public SocketFlow bandwidth(long bandwidth) { + if (bandwidth < 0) { + throw new IllegalArgumentException("invalid bandwidth"); + } else { + this.bandwidth = bandwidth; + } + return this; + } + + /** + * Returns this SocketFlow's priority. + */ + public int priority() { + return priority; + } + + /** + * Returns this SocketFlow's bandwidth. + * + * @return this SocketFlow's bandwidth, or {@code -1} if status is not OK. + */ + public long bandwidth() { + return bandwidth; + } + + /** + * Returns the Status value of this SocketFlow. NO_STATUS is returned + * if the object was not used in a call to set or get the option. + */ + public Status status() { + return status; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/jdk/net/Sockets.java Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,401 @@ +/* + * 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.*; +import java.io.IOException; +import java.io.FileDescriptor; +import java.security.PrivilegedAction; +import java.security.AccessController; +import java.lang.reflect.*; +import java.util.Set; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Collections; +import sun.net.ExtendedOptionsImpl; + +/** + * Defines static methods to set and get socket options defined by the + * {@link java.net.SocketOption} interface. All of the standard options defined + * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and + * {@link java.net.DatagramSocket} can be set this way, as well as additional + * or platform specific options supported by each socket type. + * <p> + * The {@link #supportedOptions(Class)} method can be called to determine + * the complete set of options available (per socket type) on the + * current system. + * <p> + * When a security manager is installed, some non-standard socket options + * may require a security permission before being set or get. + * The details are specified in {@link ExtendedSocketOptions}. No permission + * is required for {@link java.net.StandardSocketOption}s. + * + * @see java.nio.channels.NetworkChannel + */ +public class Sockets { + + private final static HashMap<Class<?>,Set<SocketOption<?>>> + options = new HashMap<>(); + + static { + initOptionSets(); + AccessController.doPrivileged( + new java.security.PrivilegedAction<Void>() { + public Void run() { + initMethods(); + return null; + } + } + ); + } + + private static Method siSetOption; + private static Method siGetOption; + private static Method dsiSetOption; + private static Method dsiGetOption; + + private static void initMethods() { + try { + Class<?> clazz = Class.forName("java.net.SocketSecrets"); + + siSetOption = clazz.getDeclaredMethod( + "setOption", Object.class, + SocketOption.class, Object.class + ); + siSetOption.setAccessible(true); + + siGetOption = clazz.getDeclaredMethod( + "getOption", Object.class, SocketOption.class + ); + siGetOption.setAccessible(true); + + dsiSetOption = clazz.getDeclaredMethod( + "setOption", DatagramSocket.class, + SocketOption.class, Object.class + ); + dsiSetOption.setAccessible(true); + + dsiGetOption = clazz.getDeclaredMethod( + "getOption", DatagramSocket.class, SocketOption.class + ); + dsiGetOption.setAccessible(true); + } catch (ReflectiveOperationException e) { + throw new Error(e); + } + } + + private static <T> void invokeSet( + Method method, Object socket, + SocketOption<T> option, T value) throws IOException + { + try { + method.invoke(null, socket, option, value); + } catch (Exception e) { + if (e instanceof InvocationTargetException) { + Throwable t = ((InvocationTargetException)e).getTargetException(); + if (t instanceof IOException) { + throw (IOException)t; + } + } + throw new RuntimeException(e); + } + } + + private static <T> T invokeGet( + Method method, Object socket, SocketOption<T> option) throws IOException + { + try { + return (T)method.invoke(null, socket, option); + } catch (Exception e) { + if (e instanceof InvocationTargetException) { + Throwable t = ((InvocationTargetException)e).getTargetException(); + if (t instanceof IOException) { + throw (IOException)t; + } + } + throw new RuntimeException(e); + } + } + + private Sockets() {} + + /** + * Sets the value of a socket option on a {@link java.net.Socket} + * + * @param s the socket + * @param name The socket option + * @param value The value of the socket option. May be null for some + * options. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IllegalArgumentException if the value is not valid for + * the option. + * + * @throws IOException if an I/O error occurs, or socket is closed. + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @throws NullPointerException if name is null + * + * @see java.net.StandardSocketOptions + */ + public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException + { + if (!isSupported(Socket.class, name)) { + throw new UnsupportedOperationException(name.name()); + } + invokeSet(siSetOption, s, name, value); + } + + /** + * Returns the value of a socket option from a {@link java.net.Socket} + * + * @param s the socket + * @param name The socket option + * + * @return The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @throws NullPointerException if name is null + * + * @see java.net.StandardSocketOptions + */ + public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException + { + if (!isSupported(Socket.class, name)) { + throw new UnsupportedOperationException(name.name()); + } + return invokeGet(siGetOption, s, name); + } + + /** + * Sets the value of a socket option on a {@link java.net.ServerSocket} + * + * @param s the socket + * @param name The socket option + * @param value The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IllegalArgumentException if the value is not valid for + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws NullPointerException if name is null + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @see java.net.StandardSocketOptions + */ + public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException + { + if (!isSupported(ServerSocket.class, name)) { + throw new UnsupportedOperationException(name.name()); + } + invokeSet(siSetOption, s, name, value); + } + + /** + * Returns the value of a socket option from a {@link java.net.ServerSocket} + * + * @param s the socket + * @param name The socket option + * + * @return The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws NullPointerException if name is null + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @see java.net.StandardSocketOptions + */ + public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException + { + if (!isSupported(ServerSocket.class, name)) { + throw new UnsupportedOperationException(name.name()); + } + return invokeGet(siGetOption, s, name); + } + + /** + * Sets the value of a socket option on a {@link java.net.DatagramSocket} + * or {@link java.net.MulticastSocket} + * + * @param s the socket + * @param name The socket option + * @param value The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IllegalArgumentException if the value is not valid for + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws NullPointerException if name is null + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @see java.net.StandardSocketOptions + */ + public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException + { + if (!isSupported(s.getClass(), name)) { + throw new UnsupportedOperationException(name.name()); + } + invokeSet(dsiSetOption, s, name, value); + } + + /** + * Returns the value of a socket option from a + * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket} + * + * @param s the socket + * @param name The socket option + * + * @return The value of the socket option. + * + * @throws UnsupportedOperationException if the socket does not support + * the option. + * + * @throws IOException if an I/O error occurs + * + * @throws NullPointerException if name is null + * + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission. + * + * @see java.net.StandardSocketOptions + */ + public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException + { + if (!isSupported(s.getClass(), name)) { + throw new UnsupportedOperationException(name.name()); + } + return invokeGet(dsiGetOption, s, name); + } + + /** + * Returns a set of {@link java.net.SocketOption}s supported by the + * given socket type. This set may include standard options and also + * non standard extended options. + * + * @param socketType the type of java.net socket + * + * @throws IllegalArgumentException if socketType is not a valid + * socket type from the java.net package. + */ + public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) { + Set<SocketOption<?>> set = options.get(socketType); + if (set == null) { + throw new IllegalArgumentException("unknown socket type"); + } + return set; + } + + private static boolean isSupported(Class<?> type, SocketOption<?> option) { + Set<SocketOption<?>> options = supportedOptions(type); + return options.contains(option); + } + + private static void initOptionSets() { + boolean flowsupported = ExtendedOptionsImpl.flowSupported(); + + // Socket + + Set<SocketOption<?>> set = new HashSet<>(); + set.add(StandardSocketOptions.SO_KEEPALIVE); + set.add(StandardSocketOptions.SO_SNDBUF); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_REUSEADDR); + set.add(StandardSocketOptions.SO_LINGER); + set.add(StandardSocketOptions.IP_TOS); + set.add(StandardSocketOptions.TCP_NODELAY); + if (flowsupported) { + set.add(ExtendedSocketOptions.SO_FLOW_SLA); + } + set = Collections.unmodifiableSet(set); + options.put(Socket.class, set); + + // ServerSocket + + set = new HashSet<>(); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_REUSEADDR); + set = Collections.unmodifiableSet(set); + options.put(ServerSocket.class, set); + + // DatagramSocket + + set = new HashSet<>(); + set.add(StandardSocketOptions.SO_SNDBUF); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_REUSEADDR); + set.add(StandardSocketOptions.IP_TOS); + if (flowsupported) { + set.add(ExtendedSocketOptions.SO_FLOW_SLA); + } + set = Collections.unmodifiableSet(set); + options.put(DatagramSocket.class, set); + + // MulticastSocket + + set = new HashSet<>(); + set.add(StandardSocketOptions.SO_SNDBUF); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_REUSEADDR); + set.add(StandardSocketOptions.IP_TOS); + set.add(StandardSocketOptions.IP_MULTICAST_IF); + set.add(StandardSocketOptions.IP_MULTICAST_TTL); + set.add(StandardSocketOptions.IP_MULTICAST_LOOP); + if (flowsupported) { + set.add(ExtendedSocketOptions.SO_FLOW_SLA); + } + set = Collections.unmodifiableSet(set); + options.put(MulticastSocket.class, set); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/jdk/net/package-info.java Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,32 @@ +/* + * 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. + */ + +/** + * Platform specific socket options for the {@code java.net} and {@code java.nio.channels} + * socket classes. + * + */ + +package jdk.net;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/net/ExtendedOptionsImpl.java Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,94 @@ +/* + * 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(new PrivilegedAction<Void>() { + @Override + public Void run() { + 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(); +}
--- a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Tue Aug 26 15:55:35 2014 +0400 +++ b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Fri Aug 22 16:10:50 2014 +0100 @@ -39,6 +39,7 @@ import java.util.concurrent.*; import java.util.concurrent.locks.*; import sun.net.NetHooks; +import sun.net.ExtendedOptionsImpl; /** * Base implementation of AsynchronousSocketChannel @@ -508,6 +509,9 @@ set.add(StandardSocketOptions.SO_KEEPALIVE); set.add(StandardSocketOptions.SO_REUSEADDR); set.add(StandardSocketOptions.TCP_NODELAY); + if (ExtendedOptionsImpl.flowSupported()) { + set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); + } return Collections.unmodifiableSet(set); } }
--- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Tue Aug 26 15:55:35 2014 +0400 +++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Fri Aug 22 16:10:50 2014 +0100 @@ -33,6 +33,7 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.ResourceManager; +import sun.net.ExtendedOptionsImpl; /** @@ -317,6 +318,9 @@ set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); set.add(StandardSocketOptions.IP_MULTICAST_LOOP); + if (ExtendedOptionsImpl.flowSupported()) { + set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); + } return Collections.unmodifiableSet(set); } }
--- a/src/share/classes/sun/nio/ch/Net.java Tue Aug 26 15:55:35 2014 +0400 +++ b/src/share/classes/sun/nio/ch/Net.java Fri Aug 22 16:10:50 2014 +0100 @@ -27,11 +27,13 @@ import java.io.*; import java.net.*; +import jdk.net.*; import java.nio.channels.*; import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; +import sun.net.ExtendedOptionsImpl; class Net { // package-private @@ -327,6 +329,16 @@ // only simple values supported by this method Class<?> type = name.type(); + + if (type == SocketFlow.class) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA")); + } + ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value); + return; + } + if (type != Integer.class && type != Boolean.class) throw new AssertionError("Should not reach here"); @@ -379,6 +391,16 @@ { Class<?> type = name.type(); + if (type == SocketFlow.class) { + SecurityManager sm = System.getSecurityManager(); + 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 if (type != Integer.class && type != Boolean.class) throw new AssertionError("Should not reach here");
--- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java Tue Aug 26 15:55:35 2014 +0400 +++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java Fri Aug 22 16:10:50 2014 +0100 @@ -33,6 +33,7 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; +import sun.net.ExtendedOptionsImpl; import sun.misc.IoTrace; /** @@ -237,6 +238,9 @@ // additional options required by socket adaptor set.add(StandardSocketOptions.IP_TOS); set.add(ExtendedSocketOption.SO_OOBINLINE); + if (ExtendedOptionsImpl.flowSupported()) { + set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); + } return Collections.unmodifiableSet(set); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/native/java/net/jdk_net_SocketFlow.h Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,43 @@ +/* + * 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> +/* Header for class jdk_net_SocketFlow */ + +#ifndef _Included_jdk_net_SocketFlow +#define _Included_jdk_net_SocketFlow +#ifdef __cplusplus +extern "C" { +#endif +#undef jdk_net_SocketFlow_UNSET +#define jdk_net_SocketFlow_UNSET -1L +#undef jdk_net_SocketFlow_NORMAL_PRIORITY +#define jdk_net_SocketFlow_NORMAL_PRIORITY 1L +#undef jdk_net_SocketFlow_HIGH_PRIORITY +#define jdk_net_SocketFlow_HIGH_PRIORITY 2L +#ifdef __cplusplus +} +#endif +#endif
--- a/src/share/native/java/net/net_util.h Tue Aug 26 15:55:35 2014 +0400 +++ b/src/share/native/java/net/net_util.h Fri Aug 22 16:10:50 2014 +0100 @@ -40,7 +40,7 @@ #define IPv6 2 #define NET_ERROR(env, ex, msg) \ -{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg) } +{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg); } #define CHECK_NULL(x) if ((x) == NULL) return; #define CHECK_NULL_RETURN(x, y) if ((x) == NULL) return y;
--- a/src/solaris/classes/java/net/PlainDatagramSocketImpl.java Tue Aug 26 15:55:35 2014 +0400 +++ b/src/solaris/classes/java/net/PlainDatagramSocketImpl.java Fri Aug 22 16:10:50 2014 +0100 @@ -25,6 +25,11 @@ package java.net; import java.io.IOException; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; +import jdk.net.*; +import static sun.net.ExtendedOptionsImpl.*; /* * On Unix systems we simply delegate to native methods. @@ -38,6 +43,32 @@ init(); } + protected <T> void setOption(SocketOption<T> name, T value) throws IOException { + if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + super.setOption(name, value); + } else { + if (isClosed()) { + throw new SocketException("Socket closed"); + } + checkSetOptionPermission(name); + checkValueType(value, SocketFlow.class); + setFlowOption(getFileDescriptor(), (SocketFlow)value); + } + } + + protected <T> T getOption(SocketOption<T> name) throws IOException { + if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + return super.getOption(name); + } + if (isClosed()) { + throw new SocketException("Socket closed"); + } + checkGetOptionPermission(name); + SocketFlow flow = SocketFlow.create(); + getFlowOption(getFileDescriptor(), flow); + return (T)flow; + } + protected synchronized native void bind0(int lport, InetAddress laddr) throws SocketException;
--- a/src/solaris/classes/java/net/PlainSocketImpl.java Tue Aug 26 15:55:35 2014 +0400 +++ b/src/solaris/classes/java/net/PlainSocketImpl.java Fri Aug 22 16:10:50 2014 +0100 @@ -26,6 +26,12 @@ import java.io.IOException; import java.io.FileDescriptor; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; +import jdk.net.*; + +import static sun.net.ExtendedOptionsImpl.*; /* * On Unix systems we simply delegate to native methods. @@ -51,6 +57,32 @@ this.fd = fd; } + protected <T> void setOption(SocketOption<T> name, T value) throws IOException { + if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + super.setOption(name, value); + } else { + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + checkSetOptionPermission(name); + checkValueType(value, SocketFlow.class); + setFlowOption(getFileDescriptor(), (SocketFlow)value); + } + } + + protected <T> T getOption(SocketOption<T> name) throws IOException { + if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + return super.getOption(name); + } + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + checkGetOptionPermission(name); + SocketFlow flow = SocketFlow.create(); + getFlowOption(getFileDescriptor(), flow); + return (T)flow; + } + native void socketCreate(boolean isServer) throws IOException; native void socketConnect(InetAddress address, int port, int timeout) @@ -77,5 +109,4 @@ native int socketGetOption(int opt, Object iaContainerObj) throws SocketException; native void socketSendUrgentData(int data) throws IOException; - }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/solaris/native/java/net/ExtendedOptionsImpl.c Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,329 @@ +/* + * 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"); + + /* 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 { + 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 { + 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(); +}
--- a/src/solaris/native/java/net/net_util_md.h Tue Aug 26 15:55:35 2014 +0400 +++ b/src/solaris/native/java/net/net_util_md.h Fri Aug 22 16:10:50 2014 +0100 @@ -83,7 +83,46 @@ #ifdef __solaris__ extern int net_getParam(char *driver, char *param); -#endif + +#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__ */ /* needed from libsocket on Solaris 8 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/windows/native/java/net/ExtendedOptionsImpl.c Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,62 @@ +/* + * 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" + +/* + * Class: sun_net_ExtendedOptionsImpl + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init + (JNIEnv *env, jclass UNUSED) +{ +} + +/* 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; +} + +JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported + (JNIEnv *env, jclass UNUSED) { + return JNI_FALSE; +}
--- a/test/Makefile Tue Aug 26 15:55:35 2014 +0400 +++ b/test/Makefile Fri Aug 22 16:10:50 2014 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1995, 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 @@ -524,7 +524,7 @@ # Stable samevm testruns (minus items from PROBLEM_LIST) JDK_ALL_TARGETS += jdk_net -jdk_net: $(call TestDirs, com/sun/net java/net sun/net com/oracle/net) +jdk_net: $(call TestDirs, com/sun/net java/net jdk/net sun/net com/oracle/net) $(call RunAgentvmBatch) # Stable samevm testruns (minus items from PROBLEM_LIST)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/net/Sockets/Test.java Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,231 @@ +/* + * 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. + * + * 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 8032808 + * @run main/othervm -Xcheck:jni Test + * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail + * @run main/othervm/policy=policy.success -Xcheck:jni Test success + */ + +import java.net.*; +import java.nio.channels.*; +import java.util.concurrent.*; +import jdk.net.*; + +public class Test { + + static boolean security; + static boolean success; + static int udp_port; + static InetAddress loop; + static InetSocketAddress loopad; + static SocketFlow flowIn; + static SocketChannel sc; + static Socket s; + + public static void main(String[] args) throws Exception { + + // quick check to see if supportedOptions() working before + // creating any sockets and libnet loaded + + Sockets.supportedOptions(Socket.class); + + security = System.getSecurityManager() != null; + success = security && args[0].equals("success"); + + // Main thing is to check for JNI problems + // Doesn't matter if current system does not support the option + // and currently setting the option with the loopback interface + // doesn't work either + + System.out.println ("Security Manager enabled: " + security); + if (security) { + System.out.println ("Success expected: " + success); + } + + flowIn = SocketFlow.create() + .bandwidth(1000) + .priority(SocketFlow.HIGH_PRIORITY); + + ServerSocket ss = new ServerSocket(0); + int tcp_port = ss.getLocalPort(); + loop = InetAddress.getByName("127.0.0.1"); + loopad = new InetSocketAddress(loop, tcp_port); + + DatagramSocket dg = new DatagramSocket(0); + udp_port = dg.getLocalPort(); + + s = new Socket("127.0.0.1", tcp_port); + sc = SocketChannel.open(); + sc.connect (new InetSocketAddress("127.0.0.1", tcp_port)); + + // Do some standard options tests first. Since JDK 8 doesn't have java.net API + Sockets.setOption(s, StandardSocketOptions.SO_SNDBUF, 8000); + System.out.println ("Set SO_SNDBUF to 8000\ngetting returns: "); + System.out.println (Sockets.getOption(s, StandardSocketOptions.SO_SNDBUF)); + + Sockets.setOption(ss, StandardSocketOptions.SO_RCVBUF, 5000); + System.out.println ("Set SO_RCVBUF to 5000\ngetting returns: "); + System.out.println (Sockets.getOption(s, StandardSocketOptions.SO_RCVBUF)); + + try { + Sockets.setOption(ss, StandardSocketOptions.TCP_NODELAY, true); + throw new RuntimeException("TCP_NODELAY should not be supported for ServerSocket"); + } catch (UnsupportedOperationException e) {} + try { + Sockets.setOption(dg, StandardSocketOptions.IP_MULTICAST_LOOP, true); + throw new RuntimeException("IP_MULTICAST_LOOP should not be supported for DatagramSocket"); + } catch (UnsupportedOperationException e) {} + + MulticastSocket mc0 = new MulticastSocket(0); + Sockets.setOption(mc0, StandardSocketOptions.IP_MULTICAST_LOOP, true); + System.out.println ("Expect true: " + Sockets.getOption(mc0, StandardSocketOptions.IP_MULTICAST_LOOP)); + + // Now the specific tests for SO_FLOW_SLA + + doTest1(); + doTest2(); + doTest3(); + doTest4(); + doTest5(); + doTest6(); + doTest7(); + doTest8(); + } + + static void doTest1() throws Exception { + try { + Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + if (security && !success) { + throw new RuntimeException("Test failed"); + } + } catch (SecurityException e) { + if (success) { + throw new RuntimeException("Test failed"); + } + } catch (UnsupportedOperationException e) {} + } + + static void doTest2() throws Exception { + try { + Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA); + if (security && !success) { + throw new RuntimeException("Test failed"); + } + } catch (SecurityException e) { + if (success) { + throw new RuntimeException("Test failed"); + } + } catch (UnsupportedOperationException e) {} + } + + static void doTest3() throws Exception { + try { + sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + if (security && !success) { + throw new RuntimeException("Test failed"); + } + } catch (SecurityException e) { + if (success) { + throw new RuntimeException("Test failed"); + } + } catch (UnsupportedOperationException e) {} + } + + static void doTest4() throws Exception { + try { + sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA); + if (security && !success) { + throw new RuntimeException("Test failed"); + } + } catch (SecurityException e) { + if (success) { + throw new RuntimeException("Test failed"); + } + } catch (UnsupportedOperationException e) {} + } + + static void doTest5() throws Exception { + try { + DatagramSocket dg1 = new DatagramSocket(0); + dg1.connect(loop, udp_port); + Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + if (security && !success) { + throw new RuntimeException("Test failed"); + } + } catch (SecurityException e) { + if (success) { + throw new RuntimeException("Test failed"); + } + } catch (UnsupportedOperationException e) {} + } + + static void doTest6() throws Exception { + 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); + if (security && !success) { + throw new RuntimeException("Test failed"); + } + } catch (SecurityException e) { + if (success) { + throw new RuntimeException("Test failed"); + } + } catch (UnsupportedOperationException e) {} + } + + static void doTest7() throws Exception { + try { + MulticastSocket mc1 = new MulticastSocket(0); + mc1.connect(loop, udp_port); + Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + if (security && !success) { + throw new RuntimeException("Test failed"); + } + } catch (SecurityException e) { + if (success) { + throw new RuntimeException("Test failed"); + } + } catch (UnsupportedOperationException e) {} + } + + static void doTest8() throws Exception { + try { + AsynchronousSocketChannel asc = AsynchronousSocketChannel.open(); + Future<Void> f = asc.connect(loopad); + f.get(); + asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + if (security && !success) { + throw new RuntimeException("Test failed"); + } + } catch (SecurityException e) { + if (success) { + throw new RuntimeException("Test failed"); + } + } catch (UnsupportedOperationException e) {} + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/net/Sockets/policy.fail Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,4 @@ +grant { + permission java.net.SocketPermission "127.0.0.1", "connect,accept" ; + permission java.net.SocketPermission "localhost", "listen" ; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/net/Sockets/policy.success Fri Aug 22 16:10:50 2014 +0100 @@ -0,0 +1,6 @@ +grant { + permission java.net.SocketPermission "127.0.0.1", "connect,accept" ; + permission java.net.SocketPermission "localhost", "listen" ; + permission jdk.net.NetworkPermission "setOption.SO_FLOW_SLA"; + permission jdk.net.NetworkPermission "getOption.SO_FLOW_SLA"; +};