--- a/src/java.base/share/classes/java/net/ServerSocket.java Thu Oct 17 20:27:44 2019 +0100
+++ b/src/java.base/share/classes/java/net/ServerSocket.java Thu Oct 17 20:53:35 2019 +0100
@@ -27,17 +27,12 @@
import java.io.FileDescriptor;
import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.nio.channels.ServerSocketChannel;
-import java.security.AccessController;
-import java.security.PrivilegedExceptionAction;
import java.util.Objects;
import java.util.Set;
import java.util.Collections;
-import jdk.internal.access.JavaNetSocketAccess;
-import jdk.internal.access.SharedSecrets;
+import sun.security.util.SecurityConstants;
import sun.net.PlatformSocketImpl;
/**
@@ -79,17 +74,29 @@
*
* @throws NullPointerException if impl is {@code null}.
*
+ * @throws SecurityException if a security manager is set and
+ * its {@code checkPermission} method doesn't allow
+ * {@code NetPermission("setSocketImpl")}.
* @since 12
*/
protected ServerSocket(SocketImpl impl) {
Objects.requireNonNull(impl);
+ checkPermission();
this.impl = impl;
}
+ private static Void checkPermission() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION);
+ }
+ return null;
+ }
+
/**
* Creates an unbound server socket.
*
- * @exception IOException IO error when opening the socket.
+ * @throws IOException IO error when opening the socket.
* @revised 1.4
*/
public ServerSocket() throws IOException {
@@ -106,9 +113,10 @@
* request to connect) is set to {@code 50}. If a connection
* indication arrives when the queue is full, the connection is refused.
* <p>
- * If the application has specified a server socket factory, that
- * factory's {@code createSocketImpl} method is called to create
- * the actual socket implementation. Otherwise a "plain" socket is created.
+ * If the application has specified a server socket implementation
+ * factory, that factory's {@code createSocketImpl} method is called to
+ * create the actual socket implementation. Otherwise a system-default
+ * socket implementation is created.
* <p>
* If there is a security manager,
* its {@code checkListen} method is called
@@ -120,11 +128,11 @@
* @param port the port number, or {@code 0} to use a port
* number that is automatically allocated.
*
- * @exception IOException if an I/O error occurs when opening the socket.
- * @exception SecurityException
+ * @throws IOException if an I/O error occurs when opening the socket.
+ * @throws SecurityException
* if a security manager exists and its {@code checkListen}
* method doesn't allow the operation.
- * @exception IllegalArgumentException if the port parameter is outside
+ * @throws IllegalArgumentException if the port parameter is outside
* the specified range of valid port values, which is between
* 0 and 65535, inclusive.
*
@@ -150,9 +158,10 @@
* a connection indication arrives when the queue is full, the
* connection is refused.
* <p>
- * If the application has specified a server socket factory, that
- * factory's {@code createSocketImpl} method is called to create
- * the actual socket implementation. Otherwise a "plain" socket is created.
+ * If the application has specified a server socket implementation
+ * factory, that factory's {@code createSocketImpl} method is called to
+ * create the actual socket implementation. Otherwise a system-default
+ * socket implementation is created.
* <p>
* If there is a security manager,
* its {@code checkListen} method is called
@@ -172,11 +181,11 @@
* @param backlog requested maximum length of the queue of incoming
* connections.
*
- * @exception IOException if an I/O error occurs when opening the socket.
- * @exception SecurityException
+ * @throws IOException if an I/O error occurs when opening the socket.
+ * @throws SecurityException
* if a security manager exists and its {@code checkListen}
* method doesn't allow the operation.
- * @exception IllegalArgumentException if the port parameter is outside
+ * @throws IllegalArgumentException if the port parameter is outside
* the specified range of valid port values, which is between
* 0 and 65535, inclusive.
*
@@ -225,7 +234,7 @@
* its {@code checkListen} method doesn't allow the operation.
*
* @throws IOException if an I/O error occurs when opening the socket.
- * @exception IllegalArgumentException if the port parameter is outside
+ * @throws IllegalArgumentException if the port parameter is outside
* the specified range of valid port values, which is between
* 0 and 65535, inclusive.
*
@@ -472,13 +481,19 @@
* as its arguments to ensure the operation is allowed.
* This could result in a SecurityException.
*
- * @exception IOException if an I/O error occurs when waiting for a
+ * @implNote
+ * An instance of this class using a system-default {@code SocketImpl}
+ * accepts sockets with a {@code SocketImpl} of the same type, regardless
+ * of the {@linkplain Socket#setSocketImplFactory(SocketImplFactory)
+ * client socket implementation factory}, if one has been set.
+ *
+ * @throws IOException if an I/O error occurs when waiting for a
* connection.
- * @exception SecurityException if a security manager exists and its
+ * @throws SecurityException if a security manager exists and its
* {@code checkAccept} method doesn't allow the operation.
- * @exception SocketTimeoutException if a timeout was previously set with setSoTimeout and
+ * @throws SocketTimeoutException if a timeout was previously set with setSoTimeout and
* the timeout has been reached.
- * @exception java.nio.channels.IllegalBlockingModeException
+ * @throws java.nio.channels.IllegalBlockingModeException
* if this socket has an associated channel, the channel is in
* non-blocking mode, and there is no connection ready to be
* accepted
@@ -501,15 +516,33 @@
/**
* Subclasses of ServerSocket use this method to override accept()
* to return their own subclass of socket. So a FooServerSocket
- * will typically hand this method an <i>empty</i> FooSocket. On
- * return from implAccept the FooSocket will be connected to a client.
+ * will typically hand this method a newly created, unbound, FooSocket.
+ * On return from implAccept the FooSocket will be connected to a client.
+ *
+ * <p> The behavior of this method is unspecified when invoked with a
+ * socket that is not newly created and unbound. Any socket options set
+ * on the given socket prior to invoking this method may or may not be
+ * preserved when the connection is accepted. It may not be possible to
+ * accept a connection when this socket has a {@code SocketImpl} of one
+ * type and the given socket has a {@code SocketImpl} of a completely
+ * different type.
+ *
+ * @implNote
+ * An instance of this class using a system-default {@code SocketImpl}
+ * can accept a connection with a Socket using a {@code SocketImpl} of
+ * the same type: {@code IOException} is thrown if the Socket is using
+ * a custom {@code SocketImpl}. An instance of this class using a
+ * custom {@code SocketImpl} cannot accept a connection with a Socket
+ * using a system-default {@code SocketImpl}.
*
* @param s the Socket
* @throws java.nio.channels.IllegalBlockingModeException
* if this socket has an associated channel,
* and the channel is in non-blocking mode
* @throws IOException if an I/O error occurs when waiting
- * for a connection.
+ * for a connection, or if it is not possible for this socket
+ * to accept a connection with the given socket
+ *
* @since 1.1
* @revised 1.4
* @spec JSR-51
@@ -654,7 +687,7 @@
* <p> If this socket has an associated channel then the channel is closed
* as well.
*
- * @exception IOException if an I/O error occurs when closing the socket.
+ * @throws IOException if an I/O error occurs when closing the socket.
* @revised 1.4
* @spec JSR-51
*/
@@ -690,6 +723,10 @@
/**
* Returns the binding state of the ServerSocket.
+ * <p>
+ * If the socket was bound prior to being {@linkplain #close closed},
+ * then this method will continue to return {@code true}
+ * after the socket is closed.
*
* @return true if the ServerSocket successfully bound to an address
* @since 1.4
@@ -739,7 +776,7 @@
* Retrieve setting for {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT}.
* 0 returns implies that the option is disabled (i.e., timeout of infinity).
* @return the {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT} value
- * @exception IOException if an I/O error occurs
+ * @throws IOException if an I/O error occurs
* @since 1.1
* @see #setSoTimeout(int)
*/
@@ -782,7 +819,7 @@
* is not defined.
*
* @param on whether to enable or disable the socket option
- * @exception SocketException if an error occurs enabling or
+ * @throws SocketException if an error occurs enabling or
* disabling the {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR}
* socket option, or the socket is closed.
* @since 1.4
@@ -802,7 +839,7 @@
*
* @return a {@code boolean} indicating whether or not
* {@link SocketOptions#SO_REUSEADDR SO_REUSEADDR} is enabled.
- * @exception SocketException if there is an error
+ * @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @since 1.4
* @see #setReuseAddress(boolean)
@@ -817,7 +854,8 @@
* Returns the implementation address and implementation port of
* this socket as a {@code String}.
* <p>
- * If there is a security manager set, its {@code checkConnect} method is
+ * If there is a security manager set, and this socket is
+ * {@linkplain #isBound bound}, its {@code checkConnect} method is
* called with the local address and {@code -1} as its arguments to see
* if the operation is allowed. If the operation is not allowed,
* an {@code InetAddress} representing the
@@ -831,7 +869,7 @@
return "ServerSocket[unbound]";
InetAddress in;
if (System.getSecurityManager() != null)
- in = InetAddress.getLoopbackAddress();
+ in = getInetAddress();
else
in = impl.getInetAddress();
return "ServerSocket[addr=" + in +
@@ -860,10 +898,10 @@
* This could result in a SecurityException.
*
* @param fac the desired factory.
- * @exception IOException if an I/O error occurs when setting the
+ * @throws IOException if an I/O error occurs when setting the
* socket factory.
- * @exception SocketException if the factory has already been defined.
- * @exception SecurityException if a security manager exists and its
+ * @throws SocketException if the factory has already been defined.
+ * @throws SecurityException if a security manager exists and its
* {@code checkSetFactory} method doesn't allow the operation.
* @see java.net.SocketImplFactory#createSocketImpl()
* @see SecurityManager#checkSetFactory
@@ -903,13 +941,13 @@
* requested value but the TCP receive window in sockets accepted from
* this ServerSocket will be no larger than 64K bytes.
*
- * @exception SocketException if there is an error
+ * @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
*
* @param size the size to which to set the receive buffer
* size. This value must be greater than 0.
*
- * @exception IllegalArgumentException if the
+ * @throws IllegalArgumentException if the
* value is 0 or is negative.
*
* @since 1.4
@@ -933,7 +971,7 @@
* calling {@link Socket#getReceiveBufferSize()}.
* @return the value of the {@link SocketOptions#SO_RCVBUF SO_RCVBUF}
* option for this {@code Socket}.
- * @exception SocketException if there is an error
+ * @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @see #setReceiveBufferSize(int)
* @since 1.4
@@ -1089,27 +1127,4 @@
}
return options;
}
-
- static {
- SharedSecrets.setJavaNetSocketAccess(
- new JavaNetSocketAccess() {
- @Override
- public ServerSocket newServerSocket(SocketImpl impl) {
- return new ServerSocket(impl);
- }
-
- @Override
- public SocketImpl newSocketImpl(Class<? extends SocketImpl> implClass) {
- try {
- Constructor<? extends SocketImpl> ctor =
- implClass.getDeclaredConstructor();
- return ctor.newInstance();
- } catch (NoSuchMethodException | InstantiationException |
- IllegalAccessException | InvocationTargetException e) {
- throw new AssertionError(e);
- }
- }
- }
- );
- }
}