/*
 * Copyright (c) 1995, 2025, 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 jdk.internal.event.SocketReadEvent;
import jdk.internal.event.SocketWriteEvent;
import jdk.internal.invoke.MhUtil;

import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.SocketChannel;
import java.util.Objects;
import java.util.Set;
import java.util.Collections;

/**
 * This class implements client sockets (also called just
 * "sockets"). A socket is an endpoint for communication
 * between two machines.
 * <p>
 * The actual work of the socket is performed by an instance of the
 * {@code SocketImpl} class.
 *
 * <p> The {@code Socket} 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 Socket} support 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_SNDBUF SO_SNDBUF} </th>
 *     <td> The size of the socket send buffer </td>
 *   </tr>
 *   <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_KEEPALIVE SO_KEEPALIVE} </th>
 *     <td> Keep connection alive </td>
 *   </tr>
 *   <tr>
 *     <th scope="row"> {@link java.net.StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR} </th>
 *     <td> Re-use address </td>
 *   </tr>
 *   <tr>
 *     <th scope="row"> {@link java.net.StandardSocketOptions#SO_LINGER SO_LINGER} </th>
 *     <td> Linger on close if data is present (when configured in blocking mode
 *          only) </td>
 *   </tr>
 *   <tr>
 *     <th scope="row"> {@link java.net.StandardSocketOptions#TCP_NODELAY TCP_NODELAY} </th>
 *     <td> Disable the Nagle algorithm </td>
 *   </tr>
 * </tbody>
 * </table>
 * </blockquote>
 * Additional (implementation specific) options may also be supported.
 *
 * @see     java.net.SocketImpl
 * @see     java.nio.channels.SocketChannel
 * @since   1.0
 */
public class Socket implements java.io.Closeable {
    private static final VarHandle STATE, IN, OUT;
    static {
        MethodHandles.Lookup l = MethodHandles.lookup();
        STATE = MhUtil.findVarHandle(l, "state", int.class);
        IN = MhUtil.findVarHandle(l, "in", InputStream.class);
        OUT = MhUtil.findVarHandle(l, "out", OutputStream.class);
    }

    // the underlying SocketImpl, may be null, may be swapped when connecting
    private volatile SocketImpl impl;

    // state bits
    private static final int SOCKET_CREATED = 1 << 0;   // impl.create(boolean) called
    private static final int BOUND          = 1 << 1;
    private static final int CONNECTED      = 1 << 2;
    private static final int CLOSED         = 1 << 3;
    private static final int SHUT_IN        = 1 << 9;
    private static final int SHUT_OUT       = 1 << 10;
    private volatile int state;

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

    // input/output streams
    private volatile InputStream in;
    private volatile OutputStream out;

    /**
     * Atomically sets state to the result of a bitwise OR of the current value
     * and the given mask.
     * @return the previous state value
     */
    private int getAndBitwiseOrState(int mask) {
        return (int) STATE.getAndBitwiseOr(this, mask);
    }

    private static boolean isBound(int s) {
        return (s & BOUND) != 0;
    }

    private static boolean isConnected(int s) {
        return (s & CONNECTED) != 0;
    }

    private static boolean isClosed(int s) {
        return (s & CLOSED) != 0;
    }

    private static boolean isInputShutdown(int s) {
        return (s & SHUT_IN) != 0;
    }

    private static boolean isOutputShutdown(int s) {
        return (s & SHUT_OUT) != 0;
    }

    /**
     * Creates an unconnected Socket.
     * <p>
     * If the application has specified a {@linkplain SocketImplFactory client
     * 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.
     *
     * @since   1.1
     */
    public Socket() {
        this.impl = createImpl();
    }

    /**
     * Creates an unconnected socket, specifying the type of proxy, if any,
     * that should be used regardless of any other settings.
     * <P>
     * Examples:
     * <UL> <LI>{@code Socket s = new Socket(Proxy.NO_PROXY);} will create
     * a plain socket ignoring any other proxy configuration.</LI>
     * <LI>{@code Socket s = new Socket(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("socks.mydom.com", 1080)));}
     * will create a socket connecting through the specified SOCKS proxy
     * server.</LI>
     * </UL>
     *
     * @param proxy a {@link java.net.Proxy Proxy} object specifying what kind
     *              of proxying should be used.
     * @throws IllegalArgumentException if the proxy is of an invalid type
     *          or {@code null}.
     * @see java.net.ProxySelector
     * @see java.net.Proxy
     *
     * @since   1.5
     */
    @SuppressWarnings("this-escape")
    public Socket(Proxy proxy) {
        // Create a copy of Proxy as a security measure
        if (proxy == null) {
            throw new IllegalArgumentException("Invalid Proxy");
        }
        Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY
                                          : sun.net.ApplicationProxy.create(proxy);
        Proxy.Type type = p.type();
        if (type == Proxy.Type.SOCKS || type == Proxy.Type.HTTP) {
            InetSocketAddress epoint = (InetSocketAddress) p.address();
            if (epoint.getAddress() != null) {
                checkAddress (epoint.getAddress(), "Socket");
            }
            // create a SOCKS or HTTP SocketImpl that delegates to a platform SocketImpl
            SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
            impl = (type == Proxy.Type.SOCKS) ? new SocksSocketImpl(p, delegate)
                                              : new HttpConnectSocketImpl(p, delegate, this);
        } else {
            if (p == Proxy.NO_PROXY) {
                // create a platform or custom SocketImpl for the DIRECT case
                SocketImplFactory factory = Socket.factory;
                if (factory == null) {
                    impl = SocketImpl.createPlatformSocketImpl(false);
                } else {
                    impl = factory.createSocketImpl();
                }
            } else
                throw new IllegalArgumentException("Invalid Proxy");
        }
    }

    /**
     * Creates an unconnected Socket with a user-specified
     * SocketImpl.
     *
     * @param impl an instance of a <B>SocketImpl</B>
     * the subclass wishes to use on the Socket.
     *
     * @throws    SocketException if there is an error in the underlying protocol,
     * such as a TCP error.
     *
     * @since   1.1
     */
    protected Socket(SocketImpl impl) throws SocketException {
        if (impl != null) {
            this.impl = impl;
        }
    }

    /**
     * Creates a stream socket and connects it to the specified port
     * number on the named host.
     * <p>
     * If the specified host is {@code null} it is the equivalent of
     * specifying the address as
     * {@link java.net.InetAddress#getByName InetAddress.getByName}{@code (null)}.
     * In other words, it is equivalent to specifying an address of the
     * loopback interface. </p>
     * <p>
     * If the application has specified a {@linkplain SocketImplFactory client
     * 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      host   the host name, or {@code null} for the loopback address.
     * @param      port   the port number.
     *
     * @throws     UnknownHostException if the IP address of
     * the host could not be determined.
     *
     * @throws     IOException  if an I/O error occurs when creating the socket.
     * @throws     IllegalArgumentException if the port parameter is outside
     *             the specified range of valid port values, which is between
     *             0 and 65535, inclusive.
     */
    @SuppressWarnings("this-escape")
    public Socket(String host, int port)
        throws UnknownHostException, IOException
    {
        this(host != null ? new InetSocketAddress(host, port) :
             new InetSocketAddress(InetAddress.getByName(null), port),
             (SocketAddress) null, true);
    }

    /**
     * Creates a stream socket and connects it to the specified port
     * number at the specified IP address.
     * <p>
     * If the application has specified a {@linkplain SocketImplFactory client
     * 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      address   the IP address.
     * @param      port      the port number.
     * @throws     IOException  if an I/O error occurs when creating the socket.
     * @throws     IllegalArgumentException if the port parameter is outside
     *             the specified range of valid port values, which is between
     *             0 and 65535, inclusive.
     * @throws     NullPointerException if {@code address} is null.
     */
    @SuppressWarnings("this-escape")
    public Socket(InetAddress address, int port) throws IOException {
        this(address != null ? new InetSocketAddress(address, port) : null,
             (SocketAddress) null, true);
    }

    /**
     * Creates a socket and connects it to the specified remote host on
     * the specified remote port. The Socket will also bind() to the local
     * address and port supplied.
     * <p>
     * If the specified host is {@code null} it is the equivalent of
     * specifying the address as
     * {@link java.net.InetAddress#getByName InetAddress.getByName}{@code (null)}.
     * In other words, it is equivalent to specifying an address of the
     * loopback interface. </p>
     * <p>
     * A local port number of {@code zero} will let the system pick up a
     * free port in the {@code bind} operation.</p>
     *
     * @param host the name of the remote host, or {@code null} for the loopback address.
     * @param port the remote port
     * @param localAddr the local address the socket is bound to, or
     *        {@code null} for the {@code anyLocal} address.
     * @param localPort the local port the socket is bound to, or
     *        {@code zero} for a system selected free port.
     * @throws     IOException  if an I/O error occurs when creating the socket.
     * @throws     IllegalArgumentException if the port parameter or localPort
     *             parameter is outside the specified range of valid port values,
     *             which is between 0 and 65535, inclusive.
     * @since   1.1
     */
    @SuppressWarnings("this-escape")
    public Socket(String host, int port, InetAddress localAddr,
                  int localPort) throws IOException {
        this(host != null ? new InetSocketAddress(host, port) :
               new InetSocketAddress(InetAddress.getByName(null), port),
             new InetSocketAddress(localAddr, localPort), true);
    }

    /**
     * Creates a socket and connects it to the specified remote address on
     * the specified remote port. The Socket will also bind() to the local
     * address and port supplied.
     * <p>
     * If the specified local address is {@code null} it is the equivalent of
     * specifying the address as the AnyLocal address
     * (see {@link java.net.InetAddress#isAnyLocalAddress InetAddress.isAnyLocalAddress}{@code ()}).
     * <p>
     * A local port number of {@code zero} will let the system pick up a
     * free port in the {@code bind} operation.</p>
     *
     * @param address the remote address
     * @param port the remote port
     * @param localAddr the local address the socket is bound to, or
     *        {@code null} for the {@code anyLocal} address.
     * @param localPort the local port the socket is bound to or
     *        {@code zero} for a system selected free port.
     * @throws     IOException  if an I/O error occurs when creating the socket.
     * @throws     IllegalArgumentException if the port parameter or localPort
     *             parameter is outside the specified range of valid port values,
     *             which is between 0 and 65535, inclusive.
     * @throws     NullPointerException if {@code address} is null.
     * @since   1.1
     */
    @SuppressWarnings("this-escape")
    public Socket(InetAddress address, int port, InetAddress localAddr,
                  int localPort) throws IOException {
        this(address != null ? new InetSocketAddress(address, port) : null,
             new InetSocketAddress(localAddr, localPort), true);
    }

    /**
     * Creates a stream socket and connects it to the specified port
     * number on the named host.
     * <p>
     * If the specified host is {@code null} it is the equivalent of
     * specifying the address as
     * {@link java.net.InetAddress#getByName InetAddress.getByName}{@code (null)}.
     * In other words, it is equivalent to specifying an address of the
     * loopback interface. </p>
     * <p>
     * If the application has specified a {@linkplain SocketImplFactory client
     * 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      host     the host name, or {@code null} for the loopback address.
     * @param      port     the port number.
     * @param      stream   must be true, false is not allowed.
     * @throws     IOException  if an I/O error occurs when creating the socket.
     * @throws     IllegalArgumentException if the stream parameter is {@code false}
     *             or if the port parameter is outside the specified range of valid
     *             port values, which is between 0 and 65535, inclusive.
     * @deprecated The {@code stream} parameter provided a way in early JDK releases
     *             to create a {@code Socket} that used a datagram socket. This feature
     *             no longer exists. Instead use {@link DatagramSocket} for datagram sockets.
     */
    @Deprecated(forRemoval = true, since = "1.1")
    @SuppressWarnings("this-escape")
    public Socket(String host, int port, boolean stream) throws IOException {
        this(host != null ? new InetSocketAddress(host, port) :
               new InetSocketAddress(InetAddress.getByName(null), port),
             (SocketAddress) null, stream);
    }

    /**
     * Creates a socket and connects it to the specified port number at
     * the specified IP address.
     * <p>
     * If the application has specified a {@linkplain SocketImplFactory client
     * 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      host     the IP address.
     * @param      port      the port number.
     * @param      stream    must be true, false is not allowed.
     * @throws     IOException  if an I/O error occurs when creating the socket.
     * @throws     IllegalArgumentException if the stream parameter is {@code false}
     *             or if the port parameter is outside the specified range of valid
     *             port values, which is between 0 and 65535, inclusive.
     * @throws     NullPointerException if {@code host} is null.
     * @deprecated The {@code stream} parameter provided a way in early JDK releases
     *             to create a {@code Socket} that used a datagram socket. This feature
     *             no longer exists. Instead use {@link DatagramSocket} for datagram sockets.
     */
    @Deprecated(forRemoval = true, since = "1.1")
    @SuppressWarnings("this-escape")
    public Socket(InetAddress host, int port, boolean stream) throws IOException {
        this(host != null ? new InetSocketAddress(host, port) : null,
             new InetSocketAddress(0), stream);
    }

    /**
     * Initialize a new Socket that is connected to the given remote address.
     * The socket is optionally bound to a local address before connecting.
     *
     * @param address the remote address to connect to
     * @param localAddr the local address to bind to, can be null
     * @param stream true for a stream socket, false for a datagram socket
     */
    private Socket(SocketAddress address, SocketAddress localAddr, boolean stream)
        throws IOException
    {
        Objects.requireNonNull(address);
        if (!stream) {
            throw new IllegalArgumentException(
                    "Socket constructor does not support creation of datagram sockets");
        }
        assert address instanceof InetSocketAddress;

        // create the SocketImpl and the underlying socket
        SocketImpl impl = createImpl();
        impl.create(stream);

        this.impl = impl;
        this.state = SOCKET_CREATED;

        try {
            if (localAddr != null) {
                bind(localAddr);
            }
            connect(address);
        } catch (Throwable throwable) {
            closeSuppressingExceptions(throwable);
            throw throwable;
        }
    }

    /**
     * Create a new SocketImpl for a connecting/client socket. The SocketImpl
     * is created without an underlying socket.
     */
    private static SocketImpl createImpl() {
        SocketImplFactory factory = Socket.factory;
        if (factory != null) {
            return factory.createSocketImpl();
        } else {
            // create a SOCKS SocketImpl that delegates to a platform SocketImpl
            SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
            return new SocksSocketImpl(delegate);
        }
    }

    /**
     * Returns the {@code SocketImpl} for this Socket, creating it, and the
     * underlying socket, if required.
     * @throws SocketException if creating the underlying socket fails
     */
    private SocketImpl getImpl() throws SocketException {
        if ((state & SOCKET_CREATED) == 0) {
            synchronized (socketLock) {
                int s = state;   // re-read state
                if ((s & SOCKET_CREATED) == 0) {
                    if (isClosed(s)) {
                        throw new SocketException("Socket is closed");
                    }
                    SocketImpl impl = this.impl;
                    if (impl == null) {
                        this.impl = impl = createImpl();
                    }
                    try {
                        impl.create(true);
                    } catch (SocketException e) {
                        throw e;
                    } catch (IOException e) {
                        throw new SocketException(e.getMessage(), e);
                    }
                    getAndBitwiseOrState(SOCKET_CREATED);
                }
            }
        }
        return impl;
    }

    /**
     * Returns the SocketImpl, may be null.
     */
    SocketImpl impl() {
        return impl;
    }

    /**
     * Sets the SocketImpl. The SocketImpl is connected to a peer. The behavior for
     * the case that the Socket was not a newly created Socket is unspecified. If
     * there is an existing SocketImpl then it closed to avoid leaking resources.
     * @throws SocketException if the Socket is closed
     * @apiNote For ServerSocket use when accepting connections
     */
    void setConnectedImpl(SocketImpl si) throws SocketException {
        synchronized (socketLock) {
            if ((state & CLOSED) != 0) {
                throw new SocketException("Socket is closed");
            }
            SocketImpl previous = impl;
            impl = si;
            state = (SOCKET_CREATED | BOUND | CONNECTED);
            if (previous != null) {
                in = null;
                out = null;
                previous.closeQuietly();
            }
        }
    }

    /**
     * Sets the SocketImpl.
     * @apiNote For ServerSocket use when accepting connections with a custom SocketImpl
     */
    void setImpl(SocketImpl si) {
        impl = si;
    }

    /**
     * Sets to Socket state for a newly accepted connection.
     * @apiNote For ServerSocket use when accepting connections with a custom SocketImpl
     */
    void setConnected() {
        getAndBitwiseOrState(SOCKET_CREATED | BOUND | CONNECTED);
    }

    /**
     * Connects this socket to the server.
     *
     * <p> If the connection cannot be established, then the socket is closed,
     * and an {@link IOException} is thrown.
     *
     * <p> This method is {@linkplain Thread#interrupt() interruptible} in the
     * following circumstances:
     * <ol>
     *   <li> The socket is {@linkplain SocketChannel#socket() associated} with
     *        a {@link SocketChannel SocketChannel}.
     *        In that case, interrupting a thread establishing a connection will
     *        close the underlying channel and cause this method to throw
     *        {@link ClosedByInterruptException} with the interrupt status set.
     *   <li> The socket uses the system-default socket implementation and a
     *        {@linkplain Thread#isVirtual() virtual thread} is establishing 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>
     *
     * @param   endpoint the {@code SocketAddress}
     * @throws  IOException if an error occurs during the connection, the socket
     *          is already connected or the socket is closed
     * @throws  UnknownHostException if the connection could not be established
     *          because the endpoint is an unresolved {@link InetSocketAddress}
     * @throws  java.nio.channels.IllegalBlockingModeException
     *          if this socket has an associated channel,
     *          and the channel is in non-blocking mode
     * @throws  IllegalArgumentException if endpoint is null or is a
     *          SocketAddress subclass not supported by this socket
     * @since 1.4
     */
    public void connect(SocketAddress endpoint) throws IOException {
        connect(endpoint, 0);
    }

    /**
     * Connects this socket to the server with a specified timeout value.
     * A timeout of zero is interpreted as an infinite timeout. The connection
     * will then block until established or an error occurs.
     *
     * <p> If the connection cannot be established, or the timeout expires
     * before the connection is established, then the socket is closed, and an
     * {@link IOException} is thrown.
     *
     * <p> This method is {@linkplain Thread#interrupt() interruptible} in the
     * following circumstances:
     * <ol>
     *   <li> The socket is {@linkplain SocketChannel#socket() associated} with
     *        a {@link SocketChannel SocketChannel}.
     *        In that case, interrupting a thread establishing a connection will
     *        close the underlying channel and cause this method to throw
     *        {@link ClosedByInterruptException} with the interrupt status set.
     *   <li> The socket uses the system-default socket implementation and a
     *        {@linkplain Thread#isVirtual() virtual thread} is establishing 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>
     *
     * @param   endpoint the {@code SocketAddress}
     * @param   timeout  the timeout value to be used in milliseconds.
     * @throws  IOException if an error occurs during the connection, the socket
     *          is already connected or the socket is closed
     * @throws  SocketTimeoutException if timeout expires before connecting
     * @throws  UnknownHostException if the connection could not be established
     *          because the endpoint is an unresolved {@link InetSocketAddress}
     * @throws  java.nio.channels.IllegalBlockingModeException
     *          if this socket has an associated channel,
     *          and the channel is in non-blocking mode
     * @throws  IllegalArgumentException if endpoint is null or is a
     *          SocketAddress subclass not supported by this socket, or
     *          if {@code timeout} is negative
     * @since 1.4
     */
    public void connect(SocketAddress endpoint, int timeout) throws IOException {
        if (endpoint == null)
            throw new IllegalArgumentException("connect: The address can't be null");

        if (timeout < 0)
            throw new IllegalArgumentException("connect: timeout can't be negative");

        int s = state;
        if (isClosed(s))
            throw new SocketException("Socket is closed");
        if (isConnected(s))
            throw new SocketException("Already connected");

        if (!(endpoint instanceof InetSocketAddress epoint))
            throw new IllegalArgumentException("Unsupported address type");

        InetAddress addr = epoint.getAddress();
        checkAddress(addr, "connect");

        try {
            getImpl().connect(epoint, timeout);
        } catch (IOException error) {
            closeSuppressingExceptions(error);
            throw error;
        }

        // connect will bind the socket if not previously bound
        getAndBitwiseOrState(BOUND | CONNECTED);
    }

    /**
     * Binds the socket to a local address.
     * <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   bindpoint the {@code SocketAddress} to bind to
     * @throws  IOException if the bind operation fails, the socket
     *          is already bound or the socket is closed.
     * @throws  IllegalArgumentException if bindpoint is a
     *          SocketAddress subclass not supported by this socket
     *
     * @since   1.4
     * @see #isBound()
     */
    public void bind(SocketAddress bindpoint) throws IOException {
        int s = state;
        if (isClosed(s))
            throw new SocketException("Socket is closed");
        if (isBound(s))
            throw new SocketException("Already bound");

        if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress)))
            throw new IllegalArgumentException("Unsupported address type");
        InetSocketAddress epoint = (InetSocketAddress) bindpoint;
        if (epoint != null && epoint.isUnresolved())
            throw new SocketException("Unresolved address");
        if (epoint == null) {
            epoint = new InetSocketAddress(0);
        }
        InetAddress addr = epoint.getAddress();
        int port = epoint.getPort();
        checkAddress (addr, "bind");
        getImpl().bind(addr, port);
        getAndBitwiseOrState(BOUND);
    }

    private void checkAddress(InetAddress addr, String op) {
        if (addr == null) {
            return;
        }
        if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
            throw new IllegalArgumentException(op + ": invalid address type");
        }
    }

    /**
     * Returns the address to which the socket is connected.
     * <p>
     * If the socket was connected prior to being {@link #close closed},
     * then this method will continue to return the connected address
     * after the socket is closed.
     *
     * @return  the remote IP address to which this socket is connected,
     *          or {@code null} if the socket is not connected.
     */
    public InetAddress getInetAddress() {
        if (!isConnected())
            return null;
        try {
            return getImpl().getInetAddress();
        } catch (SocketException e) {
        }
        return null;
    }

    /**
     * Gets the local address to which the socket is bound.
     *
     * @return the local address to which the socket is bound, or
     *         the wildcard address if the socket is closed or not bound yet.
     * @since   1.1
     */
    public InetAddress getLocalAddress() {
        // This is for backward compatibility
        if (!isBound())
            return InetAddress.anyLocalAddress();
        InetAddress in = null;
        try {
            in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
            if (in.isAnyLocalAddress()) {
                in = InetAddress.anyLocalAddress();
            }
        } catch (Exception e) {
            in = InetAddress.anyLocalAddress(); // "0.0.0.0"
        }
        return in;
    }

    /**
     * Returns the remote port number to which this socket is connected.
     * <p>
     * If the socket was connected prior to being {@link #close closed},
     * then this method will continue to return the connected port number
     * after the socket is closed.
     *
     * @return  the remote port number to which this socket is connected, or
     *          0 if the socket is not connected yet.
     */
    public int getPort() {
        if (!isConnected())
            return 0;
        try {
            return getImpl().getPort();
        } catch (SocketException e) {
            // Shouldn't happen as we're connected
        }
        return -1;
    }

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

    /**
     * Returns the address of the endpoint this socket is connected to, or
     * {@code null} if it is unconnected.
     * <p>
     * If the socket was connected prior to being {@link #close closed},
     * then this method will continue to return the connected address
     * after the socket is closed.
     *
     * @return a {@code SocketAddress} representing the remote endpoint of this
     *         socket, or {@code null} if it is not connected yet.
     * @see #getInetAddress()
     * @see #getPort()
     * @see #connect(SocketAddress, int)
     * @see #connect(SocketAddress)
     * @since 1.4
     */
    public SocketAddress getRemoteSocketAddress() {
        if (!isConnected())
            return null;
        return new InetSocketAddress(getInetAddress(), getPort());
    }

    /**
     * Returns the address of the endpoint this socket is bound to.
     * <p>
     * If a socket bound to an endpoint represented by an
     * {@code InetSocketAddress } is {@link #close closed},
     * then this method will continue to return an {@code InetSocketAddress}
     * after the socket is closed. In that case the returned
     * {@code InetSocketAddress}'s address is the
     * {@link InetAddress#isAnyLocalAddress wildcard} address
     * and its port is the local port that it was bound to.
     *
     * @return a {@code SocketAddress} representing the local endpoint of
     *         this socket, or {@code null} if the socket is not bound yet.
     *
     * @see #getLocalAddress()
     * @see #getLocalPort()
     * @see #bind(SocketAddress)
     * @since 1.4
     */
    public SocketAddress getLocalSocketAddress() {
        if (!isBound())
            return null;
        return new InetSocketAddress(getLocalAddress(), getLocalPort());
    }

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

    /**
     * Returns an input stream for this socket.
     *
     * <p> If this socket has an associated channel then the resulting input
     * stream delegates all of its operations to the channel.  If the channel
     * is in non-blocking mode then the input stream's {@code read} operations
     * will throw an {@link java.nio.channels.IllegalBlockingModeException}.
     *
     * <p> Reading from the input stream is {@linkplain Thread#interrupt()
     * interruptible} in the following circumstances:
     * <ol>
     *   <li> The socket is {@linkplain SocketChannel#socket() associated} with
     *        a {@link SocketChannel SocketChannel}.
     *        In that case, interrupting a thread reading from the input stream
     *        will close the underlying channel and cause the read method to
     *        throw {@link ClosedByInterruptException} with the interrupt
     *        status set.
     *   <li> The socket uses the system-default socket implementation and a
     *        {@linkplain Thread#isVirtual() virtual thread} is reading from the
     *        input stream. In that case, interrupting the virtual thread will
     *        cause it to wakeup and close the socket. The read method will then
     *        throw {@code SocketException} with the interrupt status set.
     * </ol>
     *
     * <p>Under abnormal conditions the underlying connection may be
     * broken by the remote host or the network software (for example
     * a connection reset in the case of TCP connections). When a
     * broken connection is detected by the network software the
     * following applies to the returned input stream :-
     *
     * <ul>
     *
     *   <li><p>The network software may discard bytes that are buffered
     *   by the socket. Bytes that aren't discarded by the network
     *   software can be read using {@link java.io.InputStream#read read}.
     *
     *   <li><p>If there are no bytes buffered on the socket, or all
     *   buffered bytes have been consumed by
     *   {@link java.io.InputStream#read read}, then all subsequent
     *   calls to {@link java.io.InputStream#read read} will throw an
     *   {@link java.io.IOException IOException}.
     *
     *   <li><p>If there are no bytes buffered on the socket, and the
     *   socket has not been closed using {@link #close close}, then
     *   {@link java.io.InputStream#available available} will
     *   return {@code 0}.
     *
     * </ul>
     *
     * <p> Closing the returned {@link java.io.InputStream InputStream}
     * will close the associated socket.
     *
     * @return     an input stream for reading bytes from this socket.
     * @throws     IOException  if an I/O error occurs when creating the
     *             input stream, the socket is closed, the socket is
     *             not connected, or the socket input has been shutdown
     *             using {@link #shutdownInput()}
     */
    public InputStream getInputStream() throws IOException {
        int s = state;
        if (isClosed(s))
            throw new SocketException("Socket is closed");
        if (!isConnected(s))
            throw new SocketException("Socket is not connected");
        if (isInputShutdown(s))
            throw new SocketException("Socket input is shutdown");
        InputStream in = this.in;
        if (in == null) {
            // wrap the input stream so that the close method closes this socket
            in = new SocketInputStream(this, impl.getInputStream());
            if (!IN.compareAndSet(this, null, in)) {
                in = this.in;
            }
        }
        return in;
    }

    /**
     * An InputStream that delegates read/available operations to an underlying
     * input stream. The close method is overridden to close the Socket.
     */
    private static class SocketInputStream extends InputStream {
        private final Socket parent;
        private final InputStream in;
        SocketInputStream(Socket parent, InputStream in) {
            this.parent = parent;
            this.in = in;
        }
        @Override
        public int read() throws IOException {
            byte[] a = new byte[1];
            int n = read(a, 0, 1);
            return (n > 0) ? (a[0] & 0xff) : -1;
        }
        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            if (!SocketReadEvent.enabled()) {
                return implRead(b, off, len);
            }
            long start = SocketReadEvent.timestamp();
            int nbytes = implRead(b, off, len);
            SocketReadEvent.offer(start, nbytes, parent.getRemoteSocketAddress(), getSoTimeout());
            return nbytes;
        }

        private int implRead(byte[] b, int off, int len) throws IOException {
            try {
                return in.read(b, off, len);
            } 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;
            }
        }

        private int getSoTimeout() {
            try {
                return parent.getSoTimeout();
            } catch (SocketException e) {
                // ignored - avoiding exceptions in jfr event data gathering
            }
            return 0;
        }

        @Override
        public int available() throws IOException {
            return in.available();
        }
        @Override
        public void close() throws IOException {
            parent.close();
        }
    }

    /**
     * Returns an output stream for this socket.
     *
     * <p> If this socket has an associated channel then the resulting output
     * stream delegates all of its operations to the channel.  If the channel
     * is in non-blocking mode then the output stream's {@code write}
     * operations will throw an {@link
     * java.nio.channels.IllegalBlockingModeException}.
     *
     * <p> Writing to the output stream is {@linkplain Thread#interrupt()
     * interruptible} in the following circumstances:
     * <ol>
     *   <li> The socket is {@linkplain SocketChannel#socket() associated} with
     *        a {@link SocketChannel SocketChannel}.
     *        In that case, interrupting a thread writing to the output stream
     *        will close the underlying channel and cause the write method to
     *        throw {@link ClosedByInterruptException} with the interrupt status
     *        set.
     *   <li> The socket uses the system-default socket implementation and a
     *        {@linkplain Thread#isVirtual() virtual thread} is writing to the
     *        output stream. In that case, interrupting the virtual thread will
     *        cause it to wakeup and close the socket. The write method will then
     *        throw {@code SocketException} with the interrupt status set.
     * </ol>
     *
     * <p> Closing the returned {@link java.io.OutputStream OutputStream}
     * will close the associated socket.
     *
     * @return     an output stream for writing bytes to this socket.
     * @throws IOException  if an I/O error occurs when creating the
     *         output stream, the socket is not connected or the socket is closed.
     */
    public OutputStream getOutputStream() throws IOException {
        int s = state;
        if (isClosed(s))
            throw new SocketException("Socket is closed");
        if (!isConnected(s))
            throw new SocketException("Socket is not connected");
        if (isOutputShutdown(s))
            throw new SocketException("Socket output is shutdown");
        OutputStream out = this.out;
        if (out == null) {
            // wrap the output stream so that the close method closes this socket
            out = new SocketOutputStream(this, impl.getOutputStream());
            if (!OUT.compareAndSet(this, null, out)) {
                out = this.out;
            }
        }
        return out;
    }

    /**
     * An OutputStream that delegates write operations to an underlying output
     * stream. The close method is overridden to close the Socket.
     */
    private static class SocketOutputStream extends OutputStream {
        private final Socket parent;
        private final OutputStream out;
        SocketOutputStream(Socket parent, OutputStream out) {
            this.parent = parent;
            this.out = out;
        }
        @Override
        public void write(int b) throws IOException {
            byte[] a = new byte[] { (byte) b };
            write(a, 0, 1);
        }
        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            if (!SocketWriteEvent.enabled()) {
                implWrite(b, off, len);
                return;
            }
            long start = SocketWriteEvent.timestamp();
            implWrite(b, off, len);
            SocketWriteEvent.offer(start, len, parent.getRemoteSocketAddress());
        }

        private void implWrite(byte[] b, int off, int len) throws IOException {
            try {
                out.write(b, off, len);
            } catch (InterruptedIOException e) {
                Thread thread = Thread.currentThread();
                if (thread.isVirtual() && thread.isInterrupted()) {
                    close();
                    throw new SocketException("Closed by interrupt");
                }
                throw e;
            }
        }
        @Override
        public void close() throws IOException {
            parent.close();
        }
    }

    /**
     * Enable/disable {@link StandardSocketOptions#TCP_NODELAY TCP_NODELAY}
     * (disable/enable Nagle's algorithm).
     *
     * @param on {@code true} to enable {@code TCP_NODELAY},
     * {@code false} to disable.
     *
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     *
     * @since   1.1
     *
     * @see #getTcpNoDelay()
     */
    public void setTcpNoDelay(boolean on) throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
    }

    /**
     * Tests if {@link StandardSocketOptions#TCP_NODELAY TCP_NODELAY} is enabled.
     *
     * @return a {@code boolean} indicating whether or not
     *         {@code TCP_NODELAY} 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.1
     * @see #setTcpNoDelay(boolean)
     */
    public boolean getTcpNoDelay() throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        return ((Boolean) getImpl().getOption(SocketOptions.TCP_NODELAY)).booleanValue();
    }

    /**
     * Enable/disable {@link StandardSocketOptions#SO_LINGER SO_LINGER} with the
     * specified linger time in seconds. The maximum timeout value is platform
     * specific.
     *
     * The setting only affects socket close.
     *
     * @param on     whether or not to linger on.
     * @param linger how long to linger for, if on is true.
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     * @throws  IllegalArgumentException if the linger value is negative.
     * @since 1.1
     * @see #getSoLinger()
     */
    public void setSoLinger(boolean on, int linger) throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        if (!on) {
            getImpl().setOption(SocketOptions.SO_LINGER, on);
        } else {
            if (linger < 0) {
                throw new IllegalArgumentException("invalid value for SO_LINGER");
            }
            if (linger > 65535)
                linger = 65535;
            getImpl().setOption(SocketOptions.SO_LINGER, linger);
        }
    }

    /**
     * Returns setting for {@link StandardSocketOptions#SO_LINGER SO_LINGER}.
     * -1 returns implies that the
     * option is disabled.
     *
     * The setting only affects socket close.
     *
     * @return the setting for {@code SO_LINGER}.
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     * @since   1.1
     * @see #setSoLinger(boolean, int)
     */
    public int getSoLinger() throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        Object o = getImpl().getOption(SocketOptions.SO_LINGER);
        if (o instanceof Integer i) {
            return i.intValue();
        } else {
            return -1;
        }
    }

    /**
     * Send one byte of urgent data on the socket. The byte to be sent is the lowest eight
     * bits of the data parameter. The urgent byte is
     * sent after any preceding writes to the socket OutputStream
     * and before any future writes to the OutputStream.
     * @param data The byte of data to send
     * @throws    IOException if there is an error
     *  sending the data.
     * @since 1.4
     */
    public void sendUrgentData(int data) throws IOException {
        if (!getImpl().supportsUrgentData()) {
            throw new SocketException ("Urgent data not supported");
        }
        getImpl().sendUrgentData (data);
    }

    /**
     * Enable/disable {@link SocketOptions#SO_OOBINLINE SO_OOBINLINE}
     * (receipt of TCP urgent data)
     *
     * By default, this option is disabled and TCP urgent data received on a
     * socket is silently discarded. If the user wishes to receive urgent data, then
     * this option must be enabled. When enabled, urgent data is received
     * inline with normal data.
     * <p>
     * Note, only limited support is provided for handling incoming urgent
     * data. In particular, no notification of incoming urgent data is provided
     * and there is no capability to distinguish between normal data and urgent
     * data unless provided by a higher level protocol.
     *
     * @param on {@code true} to enable {@code SO_OOBINLINE},
     *           {@code false} to disable.
     *
     * @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 #getOOBInline()
     */
    public void setOOBInline(boolean on) throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));
    }

    /**
     * Tests if {@link SocketOptions#SO_OOBINLINE SO_OOBINLINE} is enabled.
     *
     * @return a {@code boolean} indicating whether or not
     *         {@code SO_OOBINLINE} 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 #setOOBInline(boolean)
     */
    public boolean getOOBInline() throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        return ((Boolean) getImpl().getOption(SocketOptions.SO_OOBINLINE)).booleanValue();
    }

    /**
     *  Enable/disable {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT}
     *  with the specified timeout, in milliseconds. With this option set
     *  to a positive timeout value, a read() call on the InputStream associated with
     *  this Socket will block for only this amount of time.  If the timeout
     *  expires, a <B>java.net.SocketTimeoutException</B> is raised, though the
     *  Socket 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 can't be negative");
        getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
    }

    /**
     * Returns setting for {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT}.
     * 0 returns implies that the option is disabled (i.e., timeout of infinity).
     *
     * @return the setting for {@code SO_TIMEOUT}
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     *
     * @since   1.1
     * @see #setSoTimeout(int)
     */
    public int getSoTimeout() throws SocketException {
        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;
        }
    }

    /**
     * Sets the {@link StandardSocketOptions#SO_SNDBUF SO_SNDBUF} option to the
     * specified value for this {@code Socket}.
     * The {@code SO_SNDBUF} option is used by the platform's networking code
     * as a hint for the size to set the underlying network I/O buffers.
     *
     * <p>Because {@code SO_SNDBUF} is a hint, applications that want to verify
     * what size the buffers were set to should call {@link #getSendBufferSize()}.
     *
     * @param size the size to which to set the send buffer
     * size. This value must be greater than 0.
     *
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     * @throws  IllegalArgumentException if the value is 0 or is negative.
     *
     * @see #getSendBufferSize()
     * @since 1.2
     */
    public void setSendBufferSize(int size) throws SocketException {
        if (size <= 0)
            throw new IllegalArgumentException("negative send size");
        if (isClosed())
            throw new SocketException("Socket is closed");
        getImpl().setOption(SocketOptions.SO_SNDBUF, size);
    }

    /**
     * Get value of the {@link StandardSocketOptions#SO_SNDBUF SO_SNDBUF} option
     * for this {@code Socket}, that is the buffer size used by the platform
     * for output on this {@code Socket}.
     * @return the value of the {@code SO_SNDBUF} 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 #setSendBufferSize(int)
     * @since 1.2
     */
    public int getSendBufferSize() throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        int result = 0;
        Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);
        if (o instanceof Integer i) {
            result = i.intValue();
        }
        return result;
    }

    /**
     * Sets the {@link StandardSocketOptions#SO_RCVBUF SO_RCVBUF} option to the
     * specified value for this {@code Socket}. The
     * {@code SO_RCVBUF} option is used by the platform's networking code
     * as a hint for the size to set the underlying network I/O buffers.
     *
     * <p>Increasing the receive buffer size can increase the performance of
     * network I/O for high-volume connection, while decreasing it can
     * help reduce the backlog of incoming data.
     *
     * <p>Because {@code SO_RCVBUF} is a hint, applications that want to verify
     * what size the buffers were set to should call {@link #getReceiveBufferSize()}.
     *
     * <p>The value of {@code SO_RCVBUF} is also used to set the TCP receive window
     * that is advertised to the remote peer.
     * Generally, the window size can be modified at any time when a socket is
     * connected. However, if a receive window larger than 64K is required then
     * this must be requested <B>before</B> the socket is connected to the
     * remote peer. There are two cases to be aware of:
     * <ol>
     * <li>For sockets accepted from a ServerSocket, this must be done by calling
     * {@link ServerSocket#setReceiveBufferSize(int)} before the ServerSocket
     * is bound to a local address.</li>
     * <li>For client sockets, setReceiveBufferSize() must be called before
     * connecting the socket to its remote peer.</li></ol>
     * @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.
     *
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     *
     * @see #getReceiveBufferSize()
     * @see ServerSocket#setReceiveBufferSize(int)
     * @since 1.2
     */
    public void setReceiveBufferSize(int size) throws SocketException {
        if (size <= 0)
            throw new IllegalArgumentException("invalid 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 Socket}, that is the buffer size used by the platform
     * for input on this {@code Socket}.
     *
     * @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.2
     */
    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 i) {
            result = i.intValue();
        }
        return result;
    }

    /**
     * Enable/disable {@link StandardSocketOptions#SO_KEEPALIVE SO_KEEPALIVE}.
     *
     * @param on  whether or not to have socket keep alive turned on.
     * @throws SocketException if there is an error in the underlying protocol,
     *         such as a TCP error, or the socket is closed.
     * @since 1.3
     * @see #getKeepAlive()
     */
    public void setKeepAlive(boolean on) throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
    }

    /**
     * Tests if {@link StandardSocketOptions#SO_KEEPALIVE SO_KEEPALIVE} is enabled.
     *
     * @return a {@code boolean} indicating whether or not
     *         {@code SO_KEEPALIVE} 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.3
     * @see #setKeepAlive(boolean)
     */
    public boolean getKeepAlive() throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        return ((Boolean) getImpl().getOption(SocketOptions.SO_KEEPALIVE)).booleanValue();
    }

    /**
     * Sets traffic class or type-of-service octet in the IP
     * header for packets sent from this Socket.
     * As the underlying network implementation may ignore this
     * value applications should consider it a hint.
     *
     * <P> The tc <B>must</B> be in the range {@code 0 <= tc <=
     * 255} or an IllegalArgumentException will be thrown.
     * <p>Notes:
     * <p>For Internet Protocol v4 the value consists of an
     * {@code integer}, the least significant 8 bits of which
     * represent the value of the TOS octet in IP packets sent by
     * the socket.
     * RFC 1349 defines the TOS values as follows:
     *
     * <UL>
     * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
     * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
     * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
     * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
     * </UL>
     * The last low order bit is always ignored as this
     * corresponds to the MBZ (must be zero) bit.
     * <p>
     * Setting bits in the precedence field may result in a
     * SocketException indicating that the operation is not
     * permitted.
     * <p>
     * As RFC 1122 section 4.2.4.2 indicates, a compliant TCP
     * implementation should, but is not required to, let application
     * change the TOS field during the lifetime of a connection.
     * So whether the type-of-service field can be changed after the
     * TCP connection has been established depends on the implementation
     * in the underlying platform. Applications should not assume that
     * they can change the TOS field after the connection.
     * <p>
     * For Internet Protocol v6 {@code tc} is the value that
     * would be placed into the sin6_flowinfo field of the IP header.
     *
     * @param tc        an {@code int} value for the bitset.
     * @throws SocketException if there is an error setting the traffic class or type-of-service,
     *         or the socket is closed.
     * @since 1.4
     * @see #getTrafficClass
     * @see StandardSocketOptions#IP_TOS
     */
    public void setTrafficClass(int tc) throws SocketException {
        if (tc < 0 || tc > 255)
            throw new IllegalArgumentException("tc is not in range 0 -- 255");
        if (isClosed())
            throw new SocketException("Socket is closed");
        getImpl().setOption(SocketOptions.IP_TOS, tc);
    }

    /**
     * Gets traffic class or type-of-service in the IP header
     * for packets sent from this Socket
     * <p>
     * As the underlying network implementation may ignore the
     * traffic class or type-of-service set using {@link #setTrafficClass(int)}
     * this method may return a different value than was previously
     * set using the {@link #setTrafficClass(int)} method on this Socket.
     *
     * @return the traffic class or type-of-service already set
     * @throws SocketException if there is an error obtaining the traffic class
     *         or type-of-service value, or the socket is closed.
     * @since 1.4
     * @see #setTrafficClass(int)
     * @see StandardSocketOptions#IP_TOS
     */
    public int getTrafficClass() throws SocketException {
        return ((Integer) (getImpl().getOption(SocketOptions.IP_TOS))).intValue();
    }

    /**
     * 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 Socket} is created the initial setting
     * of {@code SO_REUSEADDR} is disabled.
     * <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 #isClosed()
     * @see #isBound()
     */
    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();
    }

    private void closeSuppressingExceptions(Throwable parentException) {
        try {
            close();
        } catch (IOException exception) {
            parentException.addSuppressed(exception);
        }
    }

    /**
     * Closes this socket.
     * <p>
     * Any thread currently blocked in an I/O operation upon this socket
     * will throw a {@link SocketException}.
     * <p>
     * Once a socket has been closed, it is not available for further networking
     * use (i.e. can't be reconnected or rebound) and several of the methods defined
     * by this class will throw an exception if invoked on the closed socket. A new
     * socket needs to be created.
     *
     * <p> Closing this socket will also close the socket's
     * {@link java.io.InputStream InputStream} and
     * {@link java.io.OutputStream OutputStream}.
     *
     * <p> If this socket has an associated channel then the channel is closed
     * as well.
     *
     * @throws     IOException  if an I/O error occurs when closing this socket.
     * @see #isClosed()
     */
    public void close() throws IOException {
        synchronized (socketLock) {
            if ((state & CLOSED) == 0) {
                int s = getAndBitwiseOrState(CLOSED);
                if ((s & (SOCKET_CREATED | CLOSED)) == SOCKET_CREATED) {
                    // close underlying socket if created
                    impl.close();
                }
            }
        }
    }

    /**
     * Places the input stream for this socket at "end of stream".
     * Any data sent to the input stream side of the socket is acknowledged
     * and then silently discarded.
     * <p>
     * If you read from a socket input stream after invoking this method on the
     * socket, the stream's {@code available} method will return 0, and its
     * {@code read} methods will return {@code -1} (end of stream).
     *
     * @throws IOException if an I/O error occurs when shutting down this socket, the
     *         socket is not connected or the socket is closed.
     *
     * @since 1.3
     * @see java.net.Socket#shutdownOutput()
     * @see java.net.Socket#close()
     * @see java.net.Socket#setSoLinger(boolean, int)
     * @see #isInputShutdown()
     */
    public void shutdownInput() throws IOException {
        int s = state;
        if (isClosed(s))
            throw new SocketException("Socket is closed");
        if (!isConnected(s))
            throw new SocketException("Socket is not connected");
        if (isInputShutdown(s))
            throw new SocketException("Socket input is already shutdown");
        getImpl().shutdownInput();
        getAndBitwiseOrState(SHUT_IN);
    }

    /**
     * Disables the output stream for this socket.
     * For a TCP socket, any previously written data will be sent
     * followed by TCP's normal connection termination sequence.
     *
     * If you write to a socket output stream after invoking
     * shutdownOutput() on the socket, the stream will throw
     * an IOException.
     *
     * @throws IOException if an I/O error occurs when shutting down this socket, the socket
     *         is not connected or the socket is closed.
     *
     * @since 1.3
     * @see java.net.Socket#shutdownInput()
     * @see java.net.Socket#close()
     * @see java.net.Socket#setSoLinger(boolean, int)
     * @see #isOutputShutdown()
     */
    public void shutdownOutput() throws IOException {
        int s = state;
        if (isClosed(s))
            throw new SocketException("Socket is closed");
        if (!isConnected(s))
            throw new SocketException("Socket is not connected");
        if (isOutputShutdown(s))
            throw new SocketException("Socket output is already shutdown");
        getImpl().shutdownOutput();
        getAndBitwiseOrState(SHUT_OUT);
    }

    /**
     * Converts this socket to a {@code String}.
     *
     * @return  a string representation of this socket.
     */
    public String toString() {
        try {
            if (isConnected())
                return "Socket[addr=" + getImpl().getInetAddress() +
                    ",port=" + getImpl().getPort() +
                    ",localport=" + getImpl().getLocalPort() + "]";
        } catch (SocketException e) {
        }
        return "Socket[unconnected]";
    }

    /**
     * Returns the connection state of the socket.
     * <p>
     * Note: Closing a socket doesn't clear its connection state, which means
     * this method will return {@code true} for a closed socket
     * (see {@link #isClosed()}) if it was successfully connected prior
     * to being closed.
     *
     * @return true if the socket was successfully connected to a server
     * @since 1.4
     */
    public boolean isConnected() {
        return isConnected(state);
    }

    /**
     * Returns the binding state of the socket.
     * <p>
     * Note: Closing a socket doesn't clear its binding state, which means
     * this method will return {@code true} for a closed socket
     * (see {@link #isClosed()}) if it was successfully bound prior
     * to being closed.
     *
     * @return true if the socket was successfully bound to an address
     * @since 1.4
     * @see #bind
     */
    public boolean isBound() {
        return isBound(state);
    }

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

    /**
     * Returns whether the read-half of the socket connection is closed.
     *
     * @return true if the input of the socket has been shutdown
     * @since 1.4
     * @see #shutdownInput
     */
    public boolean isInputShutdown() {
        return isInputShutdown(state);
    }

    /**
     * Returns whether the write-half of the socket connection is closed.
     *
     * @return true if the output of the socket has been shutdown
     * @since 1.4
     * @see #shutdownOutput
     */
    public boolean isOutputShutdown() {
        return isOutputShutdown(state);
    }

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

    static SocketImplFactory socketImplFactory() {
        return factory;
    }

    /**
     * Sets the client socket implementation factory for the
     * application. The factory can be specified only once.
     * <p>
     * When an application creates a new client 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 is already defined.
     * @see        java.net.SocketImplFactory#createSocketImpl()
     * @deprecated Use a {@link javax.net.SocketFactory} and subclass {@code Socket}
     *    directly.
     *    <br> This method provided a way in early JDK releases to replace the
     *    system wide implementation of {@code Socket}. It has been mostly
     *    obsolete since Java 1.4. If required, a {@code Socket} can be
     *    created to use a custom implementation by extending {@code Socket}
     *    and using the {@linkplain #Socket(SocketImpl) protected
     *    constructor} that takes an {@linkplain SocketImpl implementation}
     *    as a parameter.
     */
    @Deprecated(since = "17")
    public static synchronized void setSocketImplFactory(SocketImplFactory fac)
        throws IOException
    {
        if (factory != null) {
            throw new SocketException("factory already defined");
        }
        factory = fac;
    }

    /**
     * Sets performance preferences for this socket.
     *
     * <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. Negative
     * values represent a lower priority than positive values. 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 connected
     * will have no effect.
     *
     * @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 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}
     *
     * @since 9
     */
    public <T> Socket 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 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 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;
    }
}
