/*
 * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.net;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.channels.ServerSocketChannel;
import java.util.Objects;
import java.util.Set;
import java.util.Collections;

import sun.net.PlatformSocketImpl;

/**
 * This class implements server sockets. A server socket waits for
 * requests to come in over the network. It performs some operation
 * based on that request, and then possibly returns a result to the requester.
 * <p>
 * The actual work of the server socket is performed by an instance
 * of the {@code SocketImpl} class.
 *
 * <p> The {@code ServerSocket} class defines convenience
 * methods to set and get several socket options. This class also
 * defines the {@link #setOption(SocketOption, Object) setOption}
 * and {@link #getOption(SocketOption) getOption} methods to set
 * and query socket options.
 * A {@code ServerSocket} supports the following options:
 * <blockquote>
 * <table class="striped">
 * <caption style="display:none">Socket options</caption>
 * <thead>
 *   <tr>
 *     <th scope="col">Option Name</th>
 *     <th scope="col">Description</th>
 *   </tr>
 * </thead>
 * <tbody>
 *   <tr>
 *     <th scope="row"> {@link java.net.StandardSocketOptions#SO_RCVBUF SO_RCVBUF} </th>
 *     <td> The size of the socket receive buffer </td>
 *   </tr>
 *   <tr>
 *     <th scope="row"> {@link java.net.StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR} </th>
 *     <td> Re-use address </td>
 *   </tr>
 * </tbody>
 * </table>
 * </blockquote>
 * Additional (implementation specific) options may also be supported.
 *
 * @see     java.net.SocketImpl
 * @see     java.nio.channels.ServerSocketChannel
 * @since   1.0
 */
public class ServerSocket implements java.io.Closeable {
    // the underlying SocketImpl
    private final SocketImpl impl;

    // various states
    private volatile boolean created;   // impl.create(boolean) called
    private volatile boolean bound;
    private volatile boolean closed;

    // used to coordinate creating and closing underlying socket
    private final Object socketLock = new Object();

    /**
     * Creates a server socket with a user-specified {@code SocketImpl}.
     *
     * @param      impl an instance of a SocketImpl to use on the ServerSocket.
     *
     * @throws     NullPointerException if impl is {@code null}.
     *
     * @since 12
     */
    protected ServerSocket(SocketImpl impl) {
        this.impl = Objects.requireNonNull(impl);
    }

    /**
     * Creates an unbound server socket.
     *
     * @throws    IOException IO error when opening the socket.
     */
    public ServerSocket() throws IOException {
        this.impl = createImpl();
    }

    /**
     * Creates a server socket, bound to the specified port. A port number
     * of {@code 0} means that the port number is automatically
     * allocated, typically from an ephemeral port range. This port
     * number can then be retrieved by calling {@link #getLocalPort getLocalPort}.
     * <p>
     * The maximum queue length for incoming connection indications (a
     * 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 {@linkplain SocketImplFactory server
     * socket implementation factory}, that factory's
     * {@linkplain SocketImplFactory#createSocketImpl() createSocketImpl} method
     * is called to create the actual socket implementation. Otherwise a system-default
     * socket implementation is created.
     *
     * @param      port  the port number, or {@code 0} to use a port
     *                   number that is automatically allocated.
     *
     * @throws     IOException  if an I/O error occurs when opening the socket.
     * @throws     IllegalArgumentException if the port parameter is outside
     *             the specified range of valid port values, which is between
     *             0 and 65535, inclusive.
     */
    public ServerSocket(int port) throws IOException {
        this(port, 50, null);
    }

    /**
     * Creates a server socket and binds it to the specified local port
     * number, with the specified backlog.
     * A port number of {@code 0} means that the port number is
     * automatically allocated, typically from an ephemeral port range.
     * This port number can then be retrieved by calling
     * {@link #getLocalPort getLocalPort}.
     * <p>
     * The maximum queue length for incoming connection indications (a
     * request to connect) is set to the {@code backlog} parameter. If
     * a connection indication arrives when the queue is full, the
     * connection is refused.
     * <p>
     * If the application has specified a {@linkplain SocketImplFactory server
     * socket implementation factory}, that factory's
     * {@linkplain SocketImplFactory#createSocketImpl() createSocketImpl} method
     * is called to create the actual socket implementation. Otherwise a system-default
     * socket implementation is created.
     *
     * The {@code backlog} argument is the requested maximum number of
     * pending connections on the socket. Its exact semantics are implementation
     * specific. In particular, an implementation may impose a maximum length
     * or may choose to ignore the parameter altogether. The value provided
     * should be greater than {@code 0}. If it is less than or equal to
     * {@code 0}, then an implementation specific default will be used.
     *
     * @param      port     the port number, or {@code 0} to use a port
     *                      number that is automatically allocated.
     * @param      backlog  requested maximum length of the queue of incoming
     *                      connections.
     *
     * @throws     IOException  if an I/O error occurs when opening the socket.
     * @throws     IllegalArgumentException if the port parameter is outside
     *             the specified range of valid port values, which is between
     *             0 and 65535, inclusive.
     */
    public ServerSocket(int port, int backlog) throws IOException {
        this(port, backlog, null);
    }

    /**
     * Create a server with the specified port, listen backlog, and
     * local IP address to bind to.  The <i>bindAddr</i> argument
     * can be used on a multi-homed host for a ServerSocket that
     * will only accept connect requests to one of its addresses.
     * If <i>bindAddr</i> is null, it will default accepting
     * connections on any/all local addresses.
     * The port must be between 0 and 65535, inclusive.
     * A port number of {@code 0} means that the port number is
     * automatically allocated, typically from an ephemeral port range.
     * This port number can then be retrieved by calling
     * {@link #getLocalPort getLocalPort}.
     *
     * The {@code backlog} argument is the requested maximum number of
     * pending connections on the socket. Its exact semantics are implementation
     * specific. In particular, an implementation may impose a maximum length
     * or may choose to ignore the parameter altogether. The value provided
     * should be greater than {@code 0}. If it is less than or equal to
     * {@code 0}, then an implementation specific default will be used.
     *
     * @param port  the port number, or {@code 0} to use a port
     *              number that is automatically allocated.
     * @param backlog requested maximum length of the queue of incoming
     *                connections.
     * @param bindAddr the local InetAddress the server will bind to
     *
     * @throws  IOException if an I/O error occurs when opening the socket.
     * @throws     IllegalArgumentException if the port parameter is outside
     *             the specified range of valid port values, which is between
     *             0 and 65535, inclusive.
     * @since   1.1
     */
    @SuppressWarnings("this-escape")
    public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
        if (port < 0 || port > 0xFFFF)
            throw new IllegalArgumentException("Port value out of range: " + port);
        if (backlog < 1)
            backlog = 50;

        this.impl = createImpl();
        try {
            bind(new InetSocketAddress(bindAddr, port), backlog);
        } catch (IOException e) {
            close();
            throw e;
        }
    }

    /**
     * Create a SocketImpl for a server socket. The SocketImpl is created
     * without an underlying socket.
     */
    private static SocketImpl createImpl() {
        SocketImplFactory factory = ServerSocket.factory;
        if (factory != null) {
            return factory.createSocketImpl();
        } else {
            return SocketImpl.createPlatformSocketImpl(true);
        }
    }

    /**
     * Returns the {@code SocketImpl} for this ServerSocket, creating the
     * underlying socket if required.
     * @throws SocketException if creating the underlying socket fails
     */
    private SocketImpl getImpl() throws SocketException {
        if (!created) {
            synchronized (socketLock) {
                if (!created) {
                    if (closed) {
                        throw new SocketException("Socket is closed");
                    }
                    try {
                        impl.create(true);
                    } catch (SocketException e) {
                        throw e;
                    } catch (IOException e) {
                        throw new SocketException(e.getMessage(), e);
                    }
                    created = true;
                }
            }
        }
        return impl;
    }

    /**
     *
     * Binds the {@code ServerSocket} to a specific address
     * (IP address and port number).
     * <p>
     * If the address is {@code null}, then the system will pick up
     * an ephemeral port and a valid local address to bind the socket.
     *
     * @param   endpoint        The IP address and port number to bind to.
     * @throws  IOException if the bind operation fails, the socket
     *                      is already bound or the socket is closed.
     * @throws  IllegalArgumentException if endpoint is a
     *          SocketAddress subclass not supported by this socket
     * @since 1.4
     */
    public void bind(SocketAddress endpoint) throws IOException {
        bind(endpoint, 50);
    }

    /**
     *
     * Binds the {@code ServerSocket} to a specific address
     * (IP address and port number).
     * <p>
     * If the address is {@code null}, then the system will pick up
     * an ephemeral port and a valid local address to bind the socket.
     * <P>
     * The {@code backlog} argument is the requested maximum number of
     * pending connections on the socket. Its exact semantics are implementation
     * specific. In particular, an implementation may impose a maximum length
     * or may choose to ignore the parameter altogether. The value provided
     * should be greater than {@code 0}. If it is less than or equal to
     * {@code 0}, then an implementation specific default will be used.
     * @param   endpoint        The IP address and port number to bind to.
     * @param   backlog         requested maximum length of the queue of
     *                          incoming connections.
     * @throws  IOException if the bind operation fails, the socket
     *                      is already bound or the socket is closed.
     * @throws  IllegalArgumentException if endpoint is a
     *          SocketAddress subclass not supported by this socket
     * @since 1.4
     */
    public void bind(SocketAddress endpoint, int backlog) throws IOException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        if (isBound())
            throw new SocketException("Already bound");
        if (endpoint == null)
            endpoint = new InetSocketAddress(0);
        if (!(endpoint instanceof InetSocketAddress epoint))
            throw new IllegalArgumentException("Unsupported address type");
        if (epoint.isUnresolved())
            throw new SocketException("Unresolved address");
        if (backlog < 1)
            backlog = 50;

        // SocketImpl bind+listen throw if already bound or closed
        SocketImpl impl = getImpl();
        impl.bind(epoint.getAddress(), epoint.getPort());
        impl.listen(backlog);
        bound = true;
    }

    /**
     * Returns the local address of this server socket.
     * <p>
     * If the socket was bound prior to being {@link #close closed},
     * then this method will continue to return the local address
     * after the socket is closed.
     *
     * @return  the address to which this socket is bound,
     *          or {@code null} if the socket is unbound.
     */
    public InetAddress getInetAddress() {
        if (!isBound())
            return null;
        try {
            return getImpl().getInetAddress();
        } catch (SocketException e) {
            // nothing
            // If we're bound, the impl has been created
            // so we shouldn't get here
        }
        return null;
    }

    /**
     * Returns the port number on which this socket is listening.
     * <p>
     * If the socket was bound prior to being {@link #close closed},
     * then this method will continue to return the port number
     * after the socket is closed.
     *
     * @return  the port number to which this socket is listening or
     *          -1 if the socket is not bound yet.
     */
    public int getLocalPort() {
        if (!isBound())
            return -1;
        try {
            return getImpl().getLocalPort();
        } catch (SocketException e) {
            // nothing
            // If we're bound, the impl has been created
            // so we shouldn't get here
        }
        return -1;
    }

    /**
     * Returns the address of the endpoint this socket is bound to.
     * <p>
     * If the socket was bound prior to being {@link #close closed},
     * then this method will continue to return the address of the endpoint
     * after the socket is closed.
     *
     * @return a {@code SocketAddress} representing the local endpoint of
     *         this socket, or {@code null} if the socket is not bound yet.
     *
     * @see #getInetAddress()
     * @see #getLocalPort()
     * @see #bind(SocketAddress)
     * @since 1.4
     */
    public SocketAddress getLocalSocketAddress() {
        if (!isBound())
            return null;
        return new InetSocketAddress(getInetAddress(), getLocalPort());
    }

    /**
     * Listens for a connection to be made to this socket and accepts
     * it. The method blocks until a connection is made.
     *
     * <p> This method is {@linkplain Thread#interrupt() interruptible} in the
     * following circumstances:
     * <ol>
     *   <li> The socket is {@linkplain ServerSocketChannel#socket() associated}
     *        with a {@link ServerSocketChannel ServerSocketChannel}. In that
     *        case, interrupting a thread accepting a connection will close the
     *        underlying channel and cause this method to throw {@link
     *        java.nio.channels.ClosedByInterruptException} with the interrupt
     *        status set.
     *   <li> The socket uses the system-default socket implementation and a
     *        {@linkplain Thread#isVirtual() virtual thread} is accepting a
     *        connection. In that case, interrupting the virtual thread will
     *        cause it to wakeup and close the socket. This method will then throw
     *        {@code SocketException} with the interrupt status set.
     * </ol>
     *
     * @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, the socket is not bound or the socket is closed.
     * @throws     SocketTimeoutException if a timeout was previously set with setSoTimeout and
     *             the timeout has been reached.
     * @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
     *
     * @return the new Socket
     */
    public Socket accept() throws IOException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        if (!isBound())
            throw new SocketException("Socket is not bound yet");
        Socket s = new Socket((SocketImpl) null);
        implAccept(s);
        return s;
    }

    /**
     * Subclasses of ServerSocket use this method to override accept()
     * to return their own subclass of socket.  So a FooServerSocket
     * 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, or if it is not possible for this socket
     *         to accept a connection with the given socket
     *
     * @since   1.1
     */
    protected final void implAccept(Socket s) throws IOException {
        SocketImpl si = s.impl();

        // Socket has no SocketImpl
        if (si == null) {
            si = implAccept();
            try {
                s.setConnectedImpl(si);
            } catch (SocketException e) {
                // s has been closed so newly accepted connection needs to be closed
                si.closeQuietly();
                throw e;
            }
            return;
        }

        // Socket has a SOCKS or HTTP SocketImpl, need delegate
        if (si instanceof DelegatingSocketImpl dsi) {
            si = dsi.delegate();
            assert si instanceof PlatformSocketImpl;
        }

        // Accept connection with a platform or custom SocketImpl.
        // For the platform SocketImpl case:
        // - the connection is accepted with a new SocketImpl
        // - the SO_TIMEOUT socket option is copied to the new SocketImpl
        // - the Socket is connected to the new SocketImpl
        // - the existing/old SocketImpl is closed
        // For the custom SocketImpl case, the connection is accepted with the
        // existing custom SocketImpl.
        ensureCompatible(si);
        if (impl instanceof PlatformSocketImpl) {
            SocketImpl psi = platformImplAccept();
            si.copyOptionsTo(psi);
            try {
                s.setConnectedImpl(psi);
            } catch (SocketException e) {
                // s has been closed so newly accepted connection needs to be closed
                psi.closeQuietly();
                throw e;
            }
        } else {
            s.setImpl(null);    // temporarily break connection to impl
            try {
                customImplAccept(si);
            } finally {
                s.setImpl(si);  // restore connection to impl
            }
            s.setConnected();
        }

    }

    /**
     * Accepts a connection with a new SocketImpl.
     * @return the new SocketImpl
     */
    private SocketImpl implAccept() throws IOException {
        if (impl instanceof PlatformSocketImpl) {
            return platformImplAccept();
        } else {
            // custom server SocketImpl, client SocketImplFactory must be set
            SocketImplFactory factory = Socket.socketImplFactory();
            if (factory == null) {
                throw new IOException("An instance of " + impl.getClass() +
                    " cannot accept connection with 'null' SocketImpl:" +
                    " client socket implementation factory not set");
            }
            SocketImpl si = factory.createSocketImpl();
            customImplAccept(si);
            return si;
        }
    }

    /**
     * Accepts a connection with a new platform SocketImpl.
     * @return the new platform SocketImpl
     */
    private SocketImpl platformImplAccept() throws IOException {
        assert impl instanceof PlatformSocketImpl;

        // create a new platform SocketImpl and accept the connection
        SocketImpl psi = SocketImpl.createPlatformSocketImpl(false);
        implAccept(psi);
        return psi;
    }

    /**
     * Accepts a new connection with the given custom SocketImpl.
     */
    private void customImplAccept(SocketImpl si) throws IOException {
        assert !(impl instanceof PlatformSocketImpl)
                && !(si instanceof PlatformSocketImpl);

        si.reset();
        try {
            // custom SocketImpl may expect fd/address objects to be created
            si.fd = new FileDescriptor();
            si.address = new InetAddress();
            implAccept(si);
        } catch (Exception e) {
            si.reset();
            throw e;
        }
    }

    /**
     * Accepts a new connection so that the given SocketImpl is connected to
     * the peer.
     * @throws IOException if an I/O error occurs
     */
    private void implAccept(SocketImpl si) throws IOException {
        assert !(si instanceof DelegatingSocketImpl);

        // accept a connection
        try {
            impl.accept(si);
        } catch (SocketTimeoutException e) {
            throw e;
        } catch (InterruptedIOException e) {
            Thread thread = Thread.currentThread();
            if (thread.isVirtual() && thread.isInterrupted()) {
                close();
                throw new SocketException("Closed by interrupt");
            }
            throw e;
        }

    }

    /**
     * Throws IOException if the server SocketImpl and the given client
     * SocketImpl are not both platform or custom SocketImpls.
     */
    private void ensureCompatible(SocketImpl si) throws IOException {
        if ((impl instanceof PlatformSocketImpl) != (si instanceof PlatformSocketImpl)) {
            throw new IOException("An instance of " + impl.getClass() +
                " cannot accept a connection with an instance of " + si.getClass());
        }
    }

    /**
     * Closes this socket.
     *
     * Any thread currently blocked in {@link #accept()} will throw
     * a {@link SocketException}.
     *
     * <p> If this socket has an associated channel then the channel is closed
     * as well.
     *
     * <p> Once closed, several of the methods defined by this class will throw
     * an exception if invoked on the closed socket.
     *
     * @throws     IOException  if an I/O error occurs when closing the socket.
     */
    public void close() throws IOException {
        synchronized (socketLock) {
            if (!closed) {
                closed = true;

                // close underlying socket if created
                if (created) {
                    impl.close();
                }
            }
        }
    }

    /**
     * Returns the unique {@link java.nio.channels.ServerSocketChannel} object
     * associated with this socket, if any.
     *
     * <p> A server socket will have a channel if, and only if, the channel
     * itself was created via the {@link
     * java.nio.channels.ServerSocketChannel#open ServerSocketChannel.open}
     * method.
     *
     * @return  the server-socket channel associated with this socket,
     *          or {@code null} if this socket was not created
     *          for a channel
     *
     * @since 1.4
     */
    public ServerSocketChannel getChannel() {
        return null;
    }

    /**
     * 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
     */
    public boolean isBound() {
        return bound;
    }

    /**
     * Returns the closed state of the ServerSocket.
     *
     * @return true if the socket has been closed
     * @since 1.4
     */
    public boolean isClosed() {
        return closed;
    }

    /**
     * Enable/disable {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT} with the
     * specified timeout, in milliseconds.  With this option set to a positive
     * timeout value, a call to accept() for this ServerSocket
     * will block for only this amount of time.  If the timeout expires,
     * a {@link java.net.SocketTimeoutException} is raised, though the
     * ServerSocket is still valid. A timeout of zero is interpreted as an
     * infinite timeout.
     * The option <B>must</B> be enabled prior to entering the blocking
     * operation to have effect.
     *
     * @param timeout the specified timeout, in milliseconds
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     * @throws  IllegalArgumentException  if {@code timeout} is negative
     * @since   1.1
     * @see #getSoTimeout()
     */
    public void setSoTimeout(int timeout) throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        if (timeout < 0)
            throw new IllegalArgumentException("timeout < 0");
        getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
    }

    /**
     * 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
     * @throws IOException if an I/O error occurs or the socket is closed.
     * @since   1.1
     * @see #setSoTimeout(int)
     */
    public int getSoTimeout() throws IOException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
        /* extra type safety */
        if (o instanceof Integer i) {
            return i.intValue();
        } else {
            return 0;
        }
    }

    /**
     * Enable/disable the {@link StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR}
     * socket option.
     * <p>
     * When a TCP connection is closed the connection may remain
     * in a timeout state for a period of time after the connection
     * is closed (typically known as the {@code TIME_WAIT} state
     * or {@code 2MSL} wait state).
     * For applications using a well known socket address or port
     * it may not be possible to bind a socket to the required
     * {@code SocketAddress} if there is a connection in the
     * timeout state involving the socket address or port.
     * <p>
     * Enabling {@code SO_REUSEADDR} prior to binding the socket using
     * {@link #bind(SocketAddress)} allows the socket to be bound even
     * though a previous connection is in a timeout state.
     * <p>
     * When a {@code ServerSocket} is created the initial setting
     * of {@code SO_REUSEADDR} is not defined. Applications can use
     * {@link #getReuseAddress()} to determine the initial
     * setting of {@code SO_REUSEADDR}.
     * <p>
     * The behaviour when {@code SO_REUSEADDR} is enabled or disabled
     * after a socket is bound (See {@link #isBound()})
     * is not defined.
     *
     * @param on  whether to enable or disable the socket option
     * @throws    SocketException if an error occurs enabling or
     *            disabling the {@code SO_REUSEADDR}
     *            socket option, or the socket is closed.
     * @since 1.4
     * @see #getReuseAddress()
     * @see #bind(SocketAddress)
     * @see #isBound()
     * @see #isClosed()
     */
    public void setReuseAddress(boolean on) throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
    }

    /**
     * Tests if {@link StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR} is enabled.
     *
     * @return a {@code boolean} indicating whether or not
     *         {@code SO_REUSEADDR} is enabled.
     * @throws SocketException if there is an error in the underlying protocol, such as a TCP error,
     *         or the socket is closed.
     * @since   1.4
     * @see #setReuseAddress(boolean)
     */
    public boolean getReuseAddress() throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        return ((Boolean) (getImpl().getOption(SocketOptions.SO_REUSEADDR))).booleanValue();
    }

    /**
     * Returns the implementation address and implementation port of
     * this socket as a {@code String}.
     *
     * @return  a string representation of this socket.
     */
    public String toString() {
        if (!isBound())
            return "ServerSocket[unbound]";
        InetAddress in = impl.getInetAddress();
        return "ServerSocket[addr=" + in +
                ",localport=" + impl.getLocalPort()  + "]";
    }

    /**
     * The factory for all server sockets.
     */
    private static volatile SocketImplFactory factory;

    /**
     * Sets the server socket implementation factory for the
     * application. The factory can be specified only once.
     * <p>
     * When an application creates a new server socket, the socket
     * implementation factory's {@code createSocketImpl} method is
     * called to create the actual socket implementation.
     * <p>
     * Passing {@code null} to the method is a no-op unless the factory
     * was already set.
     *
     * @param      fac   the desired factory.
     * @throws     IOException  if an I/O error occurs when setting the
     *               socket factory.
     * @throws     SocketException  if the factory has already been defined.
     * @see        java.net.SocketImplFactory#createSocketImpl()
     * @deprecated Use a {@link javax.net.ServerSocketFactory} and subclass {@code ServerSocket}
     *    directly.
     *    <br> This method provided a way in early JDK releases to replace the
     *    system wide implementation of {@code ServerSocket}. It has been mostly
     *    obsolete since Java 1.4. If required, a {@code ServerSocket} can be
     *    created to use a custom implementation by extending {@code ServerSocket}
     *    and using the {@linkplain #ServerSocket(SocketImpl) protected
     *    constructor} that takes an {@linkplain SocketImpl implementation}
     *    as a parameter.
     */
    @Deprecated(since = "17")
    public static synchronized void setSocketFactory(SocketImplFactory fac) throws IOException {
        if (factory != null) {
            throw new SocketException("factory already defined");
        }
        factory = fac;
    }

    /**
     * Sets a default proposed value for the
     * {@link StandardSocketOptions#SO_RCVBUF SO_RCVBUF} option for sockets
     * accepted from this {@code ServerSocket}. The value actually set
     * in the accepted socket must be determined by calling
     * {@link Socket#getReceiveBufferSize()} after the socket
     * is returned by {@link #accept()}.
     * <p>
     * The value of {@code SO_RCVBUF} is used both to set the size of
     * the internal socket receive buffer, and to set the size
     * of the TCP receive window that is advertised to the remote peer.
     * <p>
     * It is possible to change the value subsequently, by calling
     * {@link Socket#setReceiveBufferSize(int)}. However, if the application
     * wishes to allow a receive window larger than 64K bytes, as defined by RFC1323
     * then the proposed value must be set in the ServerSocket <B>before</B>
     * it is bound to a local address. This implies, that the ServerSocket must be
     * created with the no-argument constructor, then setReceiveBufferSize() must
     * be called and lastly the ServerSocket is bound to an address by calling bind().
     * <p>
     * Failure to do this will not cause an error, and the buffer size may be set to the
     * requested value but the TCP receive window in sockets accepted from
     * this ServerSocket will be no larger than 64K bytes.
     *
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     *
     * @param size the size to which to set the receive buffer
     * size. This value must be greater than 0.
     *
     * @throws    IllegalArgumentException if the
     * value is 0 or is negative.
     *
     * @since 1.4
     * @see #getReceiveBufferSize
     */
    public void setReceiveBufferSize(int size) throws SocketException {
        if (size <= 0)
            throw new IllegalArgumentException("negative receive size");
        if (isClosed())
            throw new SocketException("Socket is closed");
        getImpl().setOption(SocketOptions.SO_RCVBUF, size);
    }

    /**
     * Gets the value of the {@link StandardSocketOptions#SO_RCVBUF SO_RCVBUF} option
     * for this {@code ServerSocket}, that is the proposed buffer size that
     * will be used for Sockets accepted from this {@code ServerSocket}.
     *
     * <p>Note, the value actually set in the accepted socket is determined by
     * calling {@link Socket#getReceiveBufferSize()}.
     * @return the value of the {@code SO_RCVBUF} option for this {@code Socket}.
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     * @see #setReceiveBufferSize(int)
     * @since 1.4
     */
    public int getReceiveBufferSize() throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        int result = 0;
        Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);
        if (o instanceof Integer) {
            result = ((Integer)o).intValue();
        }
        return result;
    }

    /**
     * Sets performance preferences for this ServerSocket.
     *
     * <p> Sockets use the TCP/IP protocol by default.  Some implementations
     * may offer alternative protocols which have different performance
     * characteristics than TCP/IP.  This method allows the application to
     * express its own preferences as to how these tradeoffs should be made
     * when the implementation chooses from the available protocols.
     *
     * <p> Performance preferences are described by three integers
     * whose values indicate the relative importance of short connection time,
     * low latency, and high bandwidth.  The absolute values of the integers
     * are irrelevant; in order to choose a protocol the values are simply
     * compared, with larger values indicating stronger preferences.  If the
     * application prefers short connection time over both low latency and high
     * bandwidth, for example, then it could invoke this method with the values
     * {@code (1, 0, 0)}.  If the application prefers high bandwidth above low
     * latency, and low latency above short connection time, then it could
     * invoke this method with the values {@code (0, 1, 2)}.
     *
     * <p> Invoking this method after this socket has been bound
     * will have no effect. This implies that in order to use this capability
     * requires the socket to be created with the no-argument constructor.
     *
     * @param  connectionTime
     *         An {@code int} expressing the relative importance of a short
     *         connection time
     *
     * @param  latency
     *         An {@code int} expressing the relative importance of low
     *         latency
     *
     * @param  bandwidth
     *         An {@code int} expressing the relative importance of high
     *         bandwidth
     *
     * @since 1.5
     */
    public void setPerformancePreferences(int connectionTime,
                                          int latency,
                                          int bandwidth)
    {
        /* Not implemented yet */
    }

    /**
     * Sets the value of a socket option.
     *
     * @param <T> The type of the socket option value
     * @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}
     *
     * @since 9
     */
    public <T> ServerSocket setOption(SocketOption<T> name, T value)
        throws IOException
    {
        Objects.requireNonNull(name);
        if (isClosed())
            throw new SocketException("Socket is closed");
        getImpl().setOption(name, value);
        return this;
    }

    /**
     * Returns the value of a socket option.
     *
     * @param <T> The type of the socket option value
     * @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}
     *
     * @since 9
     */
    public <T> T getOption(SocketOption<T> name) throws IOException {
        Objects.requireNonNull(name);
        if (isClosed())
            throw new SocketException("Socket is closed");
        return getImpl().getOption(name);
    }

    // cache of unmodifiable impl options. Possibly set racy, in impl we trust
    private volatile Set<SocketOption<?>> options;

    /**
     * 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 9
     */
    public Set<SocketOption<?>> supportedOptions() {
        Set<SocketOption<?>> so = options;
        if (so != null)
            return so;

        try {
            SocketImpl impl = getImpl();
            options = Collections.unmodifiableSet(impl.supportedOptions());
        } catch (IOException e) {
            options = Collections.emptySet();
        }
        return options;
    }
}
