8036979: Support java.net.SocketOption<> in java.net socket types
Reviewed-by: alanb, chegar
This commit is contained in:
parent
87a0f4a044
commit
e90c029bad
@ -94,6 +94,10 @@ SUNWprivate_1.1 {
|
||||
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;
|
||||
|
@ -29,6 +29,8 @@ import java.io.IOException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* This class represents a socket for sending and receiving datagram packets.
|
||||
@ -315,6 +317,7 @@ class DatagramSocket implements java.io.Closeable {
|
||||
}
|
||||
// creates a udp socket
|
||||
impl.create();
|
||||
impl.setDatagramSocket(this);
|
||||
created = true;
|
||||
}
|
||||
|
||||
@ -1258,4 +1261,94 @@ class DatagramSocket implements java.io.Closeable {
|
||||
}
|
||||
factory = fac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a socket option.
|
||||
*
|
||||
* @param name The socket option
|
||||
* @param value The value of the socket option. A value of {@code null}
|
||||
* may be valid for some options.
|
||||
*
|
||||
* @return this DatagramSocket
|
||||
*
|
||||
* @throws UnsupportedOperationException if the datagram 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 if the socket is closed.
|
||||
*
|
||||
* @throws SecurityException if a security manager is set and if the socket
|
||||
* option requires a security permission and if the caller does
|
||||
* not have the required permission.
|
||||
* {@link java.net.StandardSocketOptions StandardSocketOptions}
|
||||
* do not require any security permission.
|
||||
*
|
||||
* @throws NullPointerException if name is {@code null}
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public <T> DatagramSocket setOption(SocketOption<T> name, T value)
|
||||
throws IOException
|
||||
{
|
||||
getImpl().setOption(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a socket option.
|
||||
*
|
||||
* @param name The socket option
|
||||
*
|
||||
* @return The value of the socket option.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the datagram socket
|
||||
* does not support the option.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs, or if the socket is closed.
|
||||
*
|
||||
* @throws NullPointerException if name is {@code null}
|
||||
*
|
||||
* @throws SecurityException if a security manager is set and if the socket
|
||||
* option requires a security permission and if the caller does
|
||||
* not have the required permission.
|
||||
* {@link java.net.StandardSocketOptions StandardSocketOptions}
|
||||
* do not require any security permission.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public <T> T getOption(SocketOption<T> name) throws IOException {
|
||||
return getImpl().getOption(name);
|
||||
}
|
||||
|
||||
private static Set<SocketOption<?>> options;
|
||||
private static boolean optionsSet = false;
|
||||
|
||||
/**
|
||||
* Returns a set of the socket options supported by this socket.
|
||||
*
|
||||
* This method will continue to return the set of options even after
|
||||
* the socket has been closed.
|
||||
*
|
||||
* @return A set of the socket options supported by this socket. This set
|
||||
* may be empty if the socket's DatagramSocketImpl cannot be created.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public Set<SocketOption<?>> supportedOptions() {
|
||||
synchronized(DatagramSocket.class) {
|
||||
if (optionsSet) {
|
||||
return options;
|
||||
}
|
||||
try {
|
||||
DatagramSocketImpl impl = getImpl();
|
||||
options = Collections.unmodifiableSet(impl.supportedOptions());
|
||||
} catch (IOException e) {
|
||||
options = Collections.emptySet();
|
||||
}
|
||||
optionsSet = true;
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ package java.net;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* Abstract datagram and multicast socket implementation base class.
|
||||
@ -47,6 +49,20 @@ public abstract class DatagramSocketImpl implements SocketOptions {
|
||||
*/
|
||||
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
|
||||
@ -241,4 +257,116 @@ public abstract class DatagramSocketImpl implements SocketOptions {
|
||||
protected FileDescriptor getFileDescriptor() {
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to set a socket option.
|
||||
*
|
||||
* @param name The socket option
|
||||
*
|
||||
* @param value The value of the socket option. A value of {@code null}
|
||||
* may be valid for some options.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the DatagramSocketImpl does not
|
||||
* support the option
|
||||
*
|
||||
* @throws NullPointerException if name is {@code null}
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
protected <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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to get a socket option.
|
||||
*
|
||||
* @param name The socket option
|
||||
*
|
||||
* @throws UnsupportedOperationException if the DatagramSocketImpl does not
|
||||
* support the option
|
||||
*
|
||||
* @throws NullPointerException if name is {@code null}
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
protected <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");
|
||||
}
|
||||
}
|
||||
|
||||
private static final Set<SocketOption<?>> dgSocketOptions =
|
||||
new HashSet<>();
|
||||
|
||||
private static final Set<SocketOption<?>> mcSocketOptions =
|
||||
new HashSet<>();
|
||||
|
||||
static {
|
||||
dgSocketOptions.add(StandardSocketOptions.SO_SNDBUF);
|
||||
dgSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
|
||||
dgSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
|
||||
dgSocketOptions.add(StandardSocketOptions.IP_TOS);
|
||||
|
||||
mcSocketOptions.add(StandardSocketOptions.SO_SNDBUF);
|
||||
mcSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
|
||||
mcSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
|
||||
mcSocketOptions.add(StandardSocketOptions.IP_TOS);
|
||||
mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_IF);
|
||||
mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL);
|
||||
mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a set of SocketOptions supported by this impl
|
||||
* and by this impl's socket (DatagramSocket or MulticastSocket)
|
||||
*
|
||||
* @return a Set of SocketOptions
|
||||
*/
|
||||
protected Set<SocketOption<?>> supportedOptions() {
|
||||
if (getDatagramSocket() instanceof MulticastSocket) {
|
||||
return mcSocketOptions;
|
||||
} else {
|
||||
return dgSocketOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ import java.io.IOException;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* This class implements server sockets. A server socket waits for
|
||||
@ -919,4 +921,92 @@ class ServerSocket implements java.io.Closeable {
|
||||
/* Not implemented yet */
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a socket option.
|
||||
*
|
||||
* @param name The socket option
|
||||
* @param value The value of the socket option. A value of {@code null}
|
||||
* may be valid for some options.
|
||||
* @return this ServerSocket
|
||||
*
|
||||
* @throws UnsupportedOperationException if the server 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 if the socket is closed.
|
||||
*
|
||||
* @throws NullPointerException if name is {@code null}
|
||||
*
|
||||
* @throws SecurityException if a security manager is set and if the socket
|
||||
* option requires a security permission and if the caller does
|
||||
* not have the required permission.
|
||||
* {@link java.net.StandardSocketOptions StandardSocketOptions}
|
||||
* do not require any security permission.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public <T> ServerSocket setOption(SocketOption<T> name, T value)
|
||||
throws IOException
|
||||
{
|
||||
getImpl().setOption(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a socket option.
|
||||
*
|
||||
* @param name The socket option
|
||||
*
|
||||
* @return The value of the socket option.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the server socket does not
|
||||
* support the option.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs, or if the socket is closed.
|
||||
*
|
||||
* @throws NullPointerException if name is {@code null}
|
||||
*
|
||||
* @throws SecurityException if a security manager is set and if the socket
|
||||
* option requires a security permission and if the caller does
|
||||
* not have the required permission.
|
||||
* {@link java.net.StandardSocketOptions StandardSocketOptions}
|
||||
* do not require any security permission.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public <T> T getOption(SocketOption<T> name) throws IOException {
|
||||
return getImpl().getOption(name);
|
||||
}
|
||||
|
||||
private static Set<SocketOption<?>> options;
|
||||
private static boolean optionsSet = false;
|
||||
|
||||
/**
|
||||
* Returns a set of the socket options supported by this server socket.
|
||||
*
|
||||
* This method will continue to return the set of options even after
|
||||
* the socket has been closed.
|
||||
*
|
||||
* @return A set of the socket options supported by this socket. This set
|
||||
* may be empty if the socket's SocketImpl cannot be created.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public Set<SocketOption<?>> supportedOptions() {
|
||||
synchronized (ServerSocket.class) {
|
||||
if (optionsSet) {
|
||||
return options;
|
||||
}
|
||||
try {
|
||||
SocketImpl impl = getImpl();
|
||||
options = Collections.unmodifiableSet(impl.supportedOptions());
|
||||
} catch (IOException e) {
|
||||
options = Collections.emptySet();
|
||||
}
|
||||
optionsSet = true;
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ import java.nio.channels.SocketChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* This class implements client sockets (also called just
|
||||
@ -1720,4 +1722,93 @@ class Socket implements java.io.Closeable {
|
||||
{
|
||||
/* Not implemented yet */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value of a socket option.
|
||||
*
|
||||
* @param name The socket option
|
||||
* @param value The value of the socket option. A value of {@code null}
|
||||
* may be valid for some options.
|
||||
* @return this Socket
|
||||
*
|
||||
* @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 if the socket is closed.
|
||||
*
|
||||
* @throws NullPointerException if name is {@code null}
|
||||
*
|
||||
* @throws SecurityException if a security manager is set and if the socket
|
||||
* option requires a security permission and if the caller does
|
||||
* not have the required permission.
|
||||
* {@link java.net.StandardSocketOptions StandardSocketOptions}
|
||||
* do not require any security permission.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public <T> Socket setOption(SocketOption<T> name, T value) throws IOException {
|
||||
getImpl().setOption(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a socket option.
|
||||
*
|
||||
* @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, or if the socket is closed.
|
||||
*
|
||||
* @throws NullPointerException if name is {@code null}
|
||||
*
|
||||
* @throws SecurityException if a security manager is set and if the socket
|
||||
* option requires a security permission and if the caller does
|
||||
* not have the required permission.
|
||||
* {@link java.net.StandardSocketOptions StandardSocketOptions}
|
||||
* do not require any security permission.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getOption(SocketOption<T> name) throws IOException {
|
||||
return getImpl().getOption(name);
|
||||
}
|
||||
|
||||
private static Set<SocketOption<?>> options;
|
||||
private static boolean optionsSet = false;
|
||||
|
||||
/**
|
||||
* Returns a set of the socket options supported by this socket.
|
||||
*
|
||||
* This method will continue to return the set of options even after
|
||||
* the socket has been closed.
|
||||
*
|
||||
* @return A set of the socket options supported by this socket. This set
|
||||
* may be empty if the socket's SocketImpl cannot be created.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public Set<SocketOption<?>> supportedOptions() {
|
||||
synchronized (Socket.class) {
|
||||
if (optionsSet) {
|
||||
return options;
|
||||
}
|
||||
try {
|
||||
SocketImpl impl = getImpl();
|
||||
options = Collections.unmodifiableSet(impl.supportedOptions());
|
||||
} catch (IOException e) {
|
||||
options = Collections.emptySet();
|
||||
}
|
||||
optionsSet = true;
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,9 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileDescriptor;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* The abstract class {@code SocketImpl} is a common superclass
|
||||
@ -355,4 +358,106 @@ public abstract class SocketImpl implements SocketOptions {
|
||||
{
|
||||
/* Not implemented yet */
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to set a socket option.
|
||||
*
|
||||
* @param name The socket option
|
||||
*
|
||||
* @param value The value of the socket option. A value of {@code null}
|
||||
* may be valid for some options.
|
||||
*
|
||||
* @throws UnsupportedOperationException if the SocketImpl does not
|
||||
* support the option
|
||||
*
|
||||
* @throws IOException if an I/O error occurs, or if the socket is closed.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
protected <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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to get a socket option.
|
||||
*
|
||||
* @param name The socket option
|
||||
*
|
||||
* @return the value of the named option
|
||||
*
|
||||
* @throws UnsupportedOperationException if the SocketImpl does not
|
||||
* support the option.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs, or if the socket is closed.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
protected <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");
|
||||
}
|
||||
}
|
||||
|
||||
private static final Set<SocketOption<?>> socketOptions =
|
||||
new HashSet<>();
|
||||
|
||||
private static final Set<SocketOption<?>> serverSocketOptions =
|
||||
new HashSet<>();
|
||||
|
||||
static {
|
||||
socketOptions.add(StandardSocketOptions.SO_KEEPALIVE);
|
||||
socketOptions.add(StandardSocketOptions.SO_SNDBUF);
|
||||
socketOptions.add(StandardSocketOptions.SO_RCVBUF);
|
||||
socketOptions.add(StandardSocketOptions.SO_REUSEADDR);
|
||||
socketOptions.add(StandardSocketOptions.SO_LINGER);
|
||||
socketOptions.add(StandardSocketOptions.IP_TOS);
|
||||
socketOptions.add(StandardSocketOptions.TCP_NODELAY);
|
||||
|
||||
serverSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
|
||||
serverSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a set of SocketOptions supported by this impl
|
||||
* and by this impl's socket (Socket or ServerSocket)
|
||||
*
|
||||
* @return a Set of SocketOptions
|
||||
*/
|
||||
protected Set<SocketOption<?>> supportedOptions() {
|
||||
if (getSocket() != null) {
|
||||
return socketOptions;
|
||||
} else {
|
||||
return serverSocketOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
62
jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java
Normal file
62
jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java
Normal file
@ -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.
|
||||
*/
|
||||
|
||||
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.9
|
||||
*/
|
||||
@jdk.Exported
|
||||
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);
|
||||
}
|
93
jdk/src/share/classes/jdk/net/NetworkPermission.java
Normal file
93
jdk/src/share/classes/jdk/net/NetworkPermission.java
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
|
||||
@jdk.Exported
|
||||
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);
|
||||
}
|
||||
}
|
169
jdk/src/share/classes/jdk/net/SocketFlow.java
Normal file
169
jdk/src/share/classes/jdk/net/SocketFlow.java
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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.lang.annotation.Native;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
@jdk.Exported
|
||||
public class SocketFlow {
|
||||
|
||||
private static final int UNSET = -1;
|
||||
@Native public static final int NORMAL_PRIORITY = 1;
|
||||
@Native 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.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
@jdk.Exported
|
||||
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;
|
||||
}
|
||||
}
|
311
jdk/src/share/classes/jdk/net/Sockets.java
Normal file
311
jdk/src/share/classes/jdk/net/Sockets.java
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* 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.Field;
|
||||
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
|
||||
*/
|
||||
@jdk.Exported
|
||||
public class Sockets {
|
||||
|
||||
private final static HashMap<Class<?>,Set<SocketOption<?>>>
|
||||
options = new HashMap<>();
|
||||
|
||||
static {
|
||||
initOptionSets();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
s.setOption(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
|
||||
{
|
||||
return s.getOption(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
|
||||
{
|
||||
s.setOption(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
|
||||
{
|
||||
return s.getOption(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
|
||||
{
|
||||
s.setOption(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
|
||||
{
|
||||
return s.getOption(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 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 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);
|
||||
}
|
||||
}
|
34
jdk/src/share/classes/jdk/net/package-info.java
Normal file
34
jdk/src/share/classes/jdk/net/package-info.java
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
|
||||
@jdk.Exported
|
||||
package jdk.net;
|
92
jdk/src/share/classes/sun/net/ExtendedOptionsImpl.java
Normal file
92
jdk/src/share/classes/sun/net/ExtendedOptionsImpl.java
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
@ -39,6 +39,7 @@ import java.util.Collections;
|
||||
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 @@ abstract class AsynchronousSocketChannelImpl
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.util.*;
|
||||
import sun.net.ResourceManager;
|
||||
import sun.net.ExtendedOptionsImpl;
|
||||
|
||||
/**
|
||||
* An implementation of DatagramChannels.
|
||||
@ -317,6 +318,9 @@ class DatagramChannelImpl
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -27,11 +27,13 @@ package sun.nio.ch;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
public class Net {
|
||||
@ -297,6 +299,16 @@ public class Net {
|
||||
|
||||
// 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");
|
||||
|
||||
@ -349,6 +361,16 @@ public class Net {
|
||||
{
|
||||
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");
|
||||
|
@ -33,6 +33,7 @@ import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.util.*;
|
||||
import sun.net.NetHooks;
|
||||
import sun.net.ExtendedOptionsImpl;
|
||||
|
||||
|
||||
/**
|
||||
@ -237,6 +238,9 @@ class SocketChannelImpl
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
@ -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); }
|
||||
|
||||
/************************************************************************
|
||||
* Cached field IDs
|
||||
|
@ -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,42 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
|
||||
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 Set<SocketOption<?>> supportedOptions() {
|
||||
HashSet<SocketOption<?>> options = new HashSet(
|
||||
super.supportedOptions());
|
||||
|
||||
if (flowSupported()) {
|
||||
options.add(ExtendedSocketOptions.SO_FLOW_SLA);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
protected synchronized native void bind0(int lport, InetAddress laddr)
|
||||
throws SocketException;
|
||||
|
||||
|
@ -26,6 +26,12 @@ package java.net;
|
||||
|
||||
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,42 @@ class PlainSocketImpl extends AbstractPlainSocketImpl
|
||||
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;
|
||||
}
|
||||
|
||||
protected Set<SocketOption<?>> supportedOptions() {
|
||||
HashSet<SocketOption<?>> options = new HashSet(
|
||||
super.supportedOptions());
|
||||
|
||||
if (getSocket() != null && flowSupported()) {
|
||||
options.add(ExtendedSocketOptions.SO_FLOW_SLA);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
native void socketCreate(boolean isServer) throws IOException;
|
||||
|
||||
native void socketConnect(InetAddress address, int port, int timeout)
|
||||
@ -77,5 +119,4 @@ class PlainSocketImpl extends AbstractPlainSocketImpl
|
||||
native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
|
||||
|
||||
native void socketSendUrgentData(int data) throws IOException;
|
||||
|
||||
}
|
||||
|
337
jdk/src/solaris/native/java/net/ExtendedOptionsImpl.c
Normal file
337
jdk/src/solaris/native/java/net/ExtendedOptionsImpl.c
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
@ -107,6 +107,47 @@ int getDefaultIPv6Interface(struct in6_addr *target_addr);
|
||||
|
||||
#ifdef __solaris__
|
||||
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
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
65
jdk/src/windows/native/java/net/ExtendedOptionsImpl.c
Normal file
65
jdk/src/windows/native/java/net/ExtendedOptionsImpl.c
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
@ -102,7 +102,8 @@ jdk_nio = \
|
||||
jdk_net = \
|
||||
java/net \
|
||||
com/sun/net/httpserver \
|
||||
sun/net
|
||||
sun/net \
|
||||
jdk/net
|
||||
|
||||
jdk_time = \
|
||||
java/time
|
||||
@ -284,7 +285,7 @@ jdk_stable = \
|
||||
javax/accessibility \
|
||||
com/sun/java/swing \
|
||||
sun/pisces \
|
||||
com/sun/awt
|
||||
com/sun/awt
|
||||
|
||||
|
||||
###############################################################################
|
||||
@ -294,7 +295,7 @@ jdk_stable = \
|
||||
# - compact1, compact2, compact3, full JRE, JDK
|
||||
#
|
||||
# In addition they support testing of the minimal VM on compact1 and compact2.
|
||||
# Essentially this defines groups based around the specified API's and VM
|
||||
# Essentially this defines groups based around the specified API's and VM
|
||||
# services available in the runtime.
|
||||
#
|
||||
# The groups are defined hierarchically in two forms:
|
||||
@ -506,7 +507,7 @@ compact2 = \
|
||||
-:needs_jdk
|
||||
|
||||
# Tests that require compact2 API's and a full VM
|
||||
#
|
||||
#
|
||||
needs_full_vm_compact2 =
|
||||
|
||||
# Minimal VM on Compact 2 adds in some compact2 tests
|
||||
@ -590,7 +591,7 @@ needs_compact2 = \
|
||||
javax/crypto/Cipher/CipherStreamClose.java \
|
||||
sun/misc/URLClassPath/ClassnameCharTest.java \
|
||||
sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java \
|
||||
sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java
|
||||
sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java
|
||||
|
||||
# Compact 1 adds full VM tests
|
||||
#
|
||||
|
244
jdk/test/java/net/SocketOption/OptionsTest.java
Normal file
244
jdk/test/java/net/SocketOption/OptionsTest.java
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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 8036979
|
||||
* @run main/othervm -Xcheck:jni OptionsTest
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class OptionsTest {
|
||||
|
||||
static class Test {
|
||||
Test(SocketOption<?> option, Object testValue) {
|
||||
this.option = option;
|
||||
this.testValue = testValue;
|
||||
}
|
||||
static Test create (SocketOption<?> option, Object testValue) {
|
||||
return new Test(option, testValue);
|
||||
}
|
||||
Object option;
|
||||
Object testValue;
|
||||
};
|
||||
|
||||
// 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
|
||||
// these values are the same
|
||||
|
||||
static Test[] socketTests = new Test[] {
|
||||
Test.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE),
|
||||
Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)),
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
|
||||
};
|
||||
|
||||
static Test[] serverSocketTests = new Test[] {
|
||||
Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE)
|
||||
};
|
||||
|
||||
static Test[] dgSocketTests = new Test[] {
|
||||
Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
|
||||
};
|
||||
|
||||
static Test[] mcSocketTests = new Test[] {
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()),
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)),
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_LOOP, Boolean.TRUE)
|
||||
};
|
||||
|
||||
static NetworkInterface getNetworkInterface() {
|
||||
try {
|
||||
Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
|
||||
if (nifs.hasMoreElements()) {
|
||||
return (NetworkInterface)nifs.nextElement();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static void doSocketTests() throws Exception {
|
||||
try (
|
||||
ServerSocket srv = new ServerSocket(0);
|
||||
Socket c = new Socket("127.0.0.1", srv.getLocalPort());
|
||||
Socket s = srv.accept();
|
||||
) {
|
||||
for (int i=0; i<socketTests.length; i++) {
|
||||
Test test = socketTests[i];
|
||||
c.setOption((SocketOption)test.option, test.testValue);
|
||||
Object getval = c.getOption((SocketOption)test.option);
|
||||
Object legacyget = legacyGetOption(Socket.class, c,test.option);
|
||||
if (!getval.equals(legacyget)) {
|
||||
Formatter f = new Formatter();
|
||||
f.format("S Err %d: %s/%s", i, getval, legacyget);
|
||||
throw new RuntimeException(f.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doDgSocketTests() throws Exception {
|
||||
try (
|
||||
DatagramSocket c = new DatagramSocket(0);
|
||||
) {
|
||||
for (int i=0; i<dgSocketTests.length; i++) {
|
||||
Test test = dgSocketTests[i];
|
||||
c.setOption((SocketOption)test.option, test.testValue);
|
||||
Object getval = c.getOption((SocketOption)test.option);
|
||||
Object legacyget = legacyGetOption(DatagramSocket.class, c,test.option);
|
||||
if (!getval.equals(legacyget)) {
|
||||
Formatter f = new Formatter();
|
||||
f.format("DG Err %d: %s/%s", i, getval, legacyget);
|
||||
throw new RuntimeException(f.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doMcSocketTests() throws Exception {
|
||||
try (
|
||||
MulticastSocket c = new MulticastSocket(0);
|
||||
) {
|
||||
for (int i=0; i<mcSocketTests.length; i++) {
|
||||
Test test = mcSocketTests[i];
|
||||
c.setOption((SocketOption)test.option, test.testValue);
|
||||
Object getval = c.getOption((SocketOption)test.option);
|
||||
Object legacyget = legacyGetOption(MulticastSocket.class, c,test.option);
|
||||
if (!getval.equals(legacyget)) {
|
||||
Formatter f = new Formatter();
|
||||
f.format("MC Err %d: %s/%s", i, getval, legacyget);
|
||||
throw new RuntimeException(f.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doServerSocketTests() throws Exception {
|
||||
try (
|
||||
ServerSocket c = new ServerSocket(0);
|
||||
) {
|
||||
for (int i=0; i<serverSocketTests.length; i++) {
|
||||
Test test = serverSocketTests[i];
|
||||
c.setOption((SocketOption)test.option, test.testValue);
|
||||
Object getval = c.getOption((SocketOption)test.option);
|
||||
Object legacyget = legacyGetOption(
|
||||
ServerSocket.class, c, test.option
|
||||
);
|
||||
if (!getval.equals(legacyget)) {
|
||||
Formatter f = new Formatter();
|
||||
f.format("SS Err %d: %s/%s", i, getval, legacyget);
|
||||
throw new RuntimeException(f.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Object legacyGetOption(
|
||||
Class<?> type, Object s, Object option)
|
||||
|
||||
throws Exception
|
||||
{
|
||||
if (type.equals(Socket.class)) {
|
||||
Socket socket = (Socket)s;
|
||||
|
||||
if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) {
|
||||
return Boolean.valueOf(socket.getKeepAlive());
|
||||
} else if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
|
||||
return Integer.valueOf(socket.getSendBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
|
||||
return Integer.valueOf(socket.getReceiveBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
|
||||
return Boolean.valueOf(socket.getReuseAddress());
|
||||
} else if (option.equals(StandardSocketOptions.SO_LINGER)) {
|
||||
return Integer.valueOf(socket.getSoLinger());
|
||||
} else if (option.equals(StandardSocketOptions.IP_TOS)) {
|
||||
return Integer.valueOf(socket.getTrafficClass());
|
||||
} else if (option.equals(StandardSocketOptions.TCP_NODELAY)) {
|
||||
return Boolean.valueOf(socket.getTcpNoDelay());
|
||||
} else {
|
||||
throw new RuntimeException("unexecpted socket option");
|
||||
}
|
||||
} else if (type.equals(ServerSocket.class)) {
|
||||
ServerSocket socket = (ServerSocket)s;
|
||||
if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
|
||||
return Integer.valueOf(socket.getReceiveBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
|
||||
return Boolean.valueOf(socket.getReuseAddress());
|
||||
} else {
|
||||
throw new RuntimeException("unexecpted socket option");
|
||||
}
|
||||
} else if (type.equals(DatagramSocket.class)) {
|
||||
DatagramSocket socket = (DatagramSocket)s;
|
||||
|
||||
if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
|
||||
return Integer.valueOf(socket.getSendBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
|
||||
return Integer.valueOf(socket.getReceiveBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
|
||||
return Boolean.valueOf(socket.getReuseAddress());
|
||||
} else if (option.equals(StandardSocketOptions.IP_TOS)) {
|
||||
return Integer.valueOf(socket.getTrafficClass());
|
||||
} else {
|
||||
throw new RuntimeException("unexecpted socket option");
|
||||
}
|
||||
|
||||
} else if (type.equals(MulticastSocket.class)) {
|
||||
MulticastSocket socket = (MulticastSocket)s;
|
||||
|
||||
if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
|
||||
return Integer.valueOf(socket.getSendBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
|
||||
return Integer.valueOf(socket.getReceiveBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
|
||||
return Boolean.valueOf(socket.getReuseAddress());
|
||||
} else if (option.equals(StandardSocketOptions.IP_TOS)) {
|
||||
return Integer.valueOf(socket.getTrafficClass());
|
||||
} else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) {
|
||||
return socket.getNetworkInterface();
|
||||
} else if (option.equals(StandardSocketOptions.IP_MULTICAST_TTL)) {
|
||||
return Integer.valueOf(socket.getTimeToLive());
|
||||
} else if (option.equals(StandardSocketOptions.IP_MULTICAST_LOOP)) {
|
||||
return Boolean.valueOf(socket.getLoopbackMode());
|
||||
} else {
|
||||
throw new RuntimeException("unexecpted socket option");
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("unexecpted socket type");
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
doSocketTests();
|
||||
doServerSocketTests();
|
||||
doDgSocketTests();
|
||||
doMcSocketTests();
|
||||
}
|
||||
}
|
130
jdk/test/jdk/net/Sockets/Test.java
Normal file
130
jdk/test/jdk/net/Sockets/Test.java
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
interface Runner {
|
||||
public void run() throws Exception;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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 {
|
||||
try {
|
||||
func.run();
|
||||
if (security && !success) {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
if (success) {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
} catch (UnsupportedOperationException e) {}
|
||||
}
|
||||
}
|
4
jdk/test/jdk/net/Sockets/policy.fail
Normal file
4
jdk/test/jdk/net/Sockets/policy.fail
Normal file
@ -0,0 +1,4 @@
|
||||
grant {
|
||||
permission java.net.SocketPermission "127.0.0.1", "connect,accept" ;
|
||||
permission java.net.SocketPermission "localhost", "listen" ;
|
||||
};
|
6
jdk/test/jdk/net/Sockets/policy.success
Normal file
6
jdk/test/jdk/net/Sockets/policy.success
Normal file
@ -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";
|
||||
};
|
Loading…
Reference in New Issue
Block a user