Package java.net

Source Code of java.net.Socket$ConnectLock

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

package java.net;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.SocketChannel;
import java.security.AccessController;

import org.apache.harmony.luni.net.NetUtil;
import org.apache.harmony.luni.net.PlainSocketImpl;
import org.apache.harmony.luni.platform.Platform;
import org.apache.harmony.luni.util.Msg;
import org.apache.harmony.luni.util.PriviAction;

/**
* This class represents sockets to be used in connection-oriented (streaming)
* protocols.
*/
public class Socket {

    SocketImpl impl;

    static SocketImplFactory factory;

    private volatile boolean isCreated = false;

    private boolean isBound = false;

    private boolean isConnected = false;

    private boolean isClosed = false;

    private boolean isInputShutdown = false;

    private boolean isOutputShutdown = false;

    private static class ConnectLock {
    }

    private Object connectLock = new ConnectLock();

    private Proxy proxy;

    static final int MULTICAST_IF = 1;

    static final int MULTICAST_TTL = 2;

    static final int TCP_NODELAY = 4;

    static final int FLAG_SHUTDOWN = 8;
  
    static {
        Platform.getNetworkSystem().oneTimeInitialization(true);
    }

    /**
     * Construct a connection-oriented Socket. The Socket is created in the
     * <code>factory</code> if declared, or otherwise of the default type.
     *
     * @see SocketImplFactory
     */
    public Socket() {
        impl = factory != null ? factory.createSocketImpl()
                : new PlainSocketImpl();
    }

    /**
     * Constructs a connection-oriented Socket with specified <code>proxy</code>.
     *
     * Method <code>checkConnect</code> is called if a security manager
     * exists, and the proxy host address and port number are passed as
     * parameters.
     *
     * @param proxy
     *            the specified proxy for this Socket.
     * @throws IllegalArgumentException
     *             if the proxy is null or of an invalid type.
     * @throws SecurityException
     *             if a security manager exists and it denies the permission to
     *             connect to proxy.
     */
    public Socket(Proxy proxy) {
        if (null == proxy || Proxy.Type.HTTP == proxy.type()) {
            // KA023=Proxy is null or invalid type
            throw new IllegalArgumentException(Msg.getString("KA023")); //$NON-NLS-1$
        }
        InetSocketAddress address = (InetSocketAddress) proxy.address();
        if (null != address) {
            InetAddress addr = address.getAddress();
            String host;
            if (null != addr) {
                host = addr.getHostAddress();
            } else {
                host = address.getHostName();
            }
            int port = address.getPort();
            checkConnectPermission(host, port);
        }
        impl = factory != null ? factory.createSocketImpl()
                : new PlainSocketImpl(proxy);
        this.proxy = proxy;
    }

    /**
     * Construct a stream socket connected to the nominated destination
     * host/port. By default, the socket binds it to any available port on the
     * default localhost.
     *
     * @param dstName
     *            the destination host to connect to
     * @param dstPort
     *            the port on the destination host to connect to
     *
     * @throws UnknownHostException
     *             if the host cannot be resolved
     * @throws IOException
     *             if an error occurs while instantiating the socket
     */
    public Socket(String dstName, int dstPort) throws UnknownHostException,
            IOException {
        this();
        InetAddress dstAddress = InetAddress.getByName(dstName);
        checkDestination(dstAddress, dstPort);
        startupSocket(dstAddress, dstPort, null, 0, true);
    }

    /**
     * Construct a stream socket connected to the nominated destination
     * host/port. The socket is bound it to the nominated localAddress/port.
     *
     * @param dstName
     *            the destination host to connect to
     * @param dstPort
     *            the port on the destination host to connect to
     * @param localAddress
     *            the local host address to bind to
     * @param localPort
     *            the local port to bind to
     *
     * @throws UnknownHostException
     *             if the host cannot be resolved
     * @throws IOException
     *             if an error occurs while instantiating the socket
     */
    public Socket(String dstName, int dstPort, InetAddress localAddress,
            int localPort) throws IOException {
        this();
        InetAddress dstAddress = InetAddress.getByName(dstName);
        checkDestination(dstAddress, dstPort);
        startupSocket(dstAddress, dstPort, localAddress, localPort, true);
    }

    /**
     * Answer a new socket. This constructor is deprecated.
     *
     * @param hostName
     *            the host name
     * @param port
     *            the port on the host
     * @param streaming
     *            if true, answer a stream socket, else answer a a datagram
     *            socket.
     *
     * @throws UnknownHostException
     *             if the host cannot be resolved
     * @throws IOException
     *             if an error occurs while instantiating the socket
     *
     * @deprecated As of JDK 1.1, replaced by Socket
     * @see #Socket(String,int)
     */
    @Deprecated
    public Socket(String hostName, int port, boolean streaming)
            throws IOException {
        this();
        InetAddress host = InetAddress.getByName(hostName);
        checkDestination(host, port);
        startupSocket(host, port, null, 0, streaming);
    }

    /**
     * Construct a stream socket connected to the nominated destination host
     * address/port. By default, the socket binds it to any available port on
     * the default localhost.
     *
     * @param dstAddress
     *            the destination host address to connect to
     * @param dstPort
     *            the port on the destination host to connect to
     *
     * @throws IOException
     *             if an error occurs while instantiating the socket
     */
    public Socket(InetAddress dstAddress, int dstPort) throws IOException {
        this();
        checkDestination(dstAddress, dstPort);
        startupSocket(dstAddress, dstPort, null, 0, true);
    }

    /**
     * Construct a stream socket connected to the nominated destination host
     * address/port. The socket is bound it to the nominated localAddress/port.
     *
     * @param dstAddress
     *            the destination host address to connect to
     * @param dstPort
     *            the port on the destination host to connect to
     * @param localAddress
     *            the local host address to bind to
     * @param localPort
     *            the local port to bind to
     *
     * @throws IOException
     *             if an error occurs while instantiating the socket
     */
    public Socket(InetAddress dstAddress, int dstPort,
            InetAddress localAddress, int localPort) throws IOException {
        this();
        checkDestination(dstAddress, dstPort);
        startupSocket(dstAddress, dstPort, localAddress, localPort, true);
    }

    /**
     * Answer a new socket. This constructor is deprecated.
     *
     * @param addr
     *            the internet address
     * @param port
     *            the port on the host
     * @param streaming
     *            if true, answer a stream socket, else answer a datagram
     *            socket.
     *
     * @throws UnknownHostException
     *             if the host cannot be resolved
     * @throws IOException
     *             if an error occurs while instantiating the socket
     *
     * @deprecated As of JDK 1.1, replaced by Socket
     * @see #Socket(InetAddress,int)
     */
    @Deprecated
    public Socket(InetAddress addr, int port, boolean streaming)
            throws IOException {
        this();
        checkDestination(addr, port);
        startupSocket(addr, port, null, 0, streaming);
    }

    /**
     * Creates an unconnected socket, wrapping the <code>socketImpl</code>
     * argument.
     *
     * @param anImpl
     *            the socket to wrap
     *
     * @throws SocketException
     *             if an error occurs assigning the implementation
     */
    protected Socket(SocketImpl anImpl) throws SocketException {
        impl = anImpl;
    }

    /**
     * Check the connection destination satisfies the security policy and is in
     * the valid port range.
     *
     * @param destAddr
     *            the destination host address
     * @param dstPort
     *            the port on the destination host
     */
    void checkDestination(InetAddress destAddr, int dstPort) {
        if (dstPort < 0 || dstPort > 65535) {
            throw new IllegalArgumentException(Msg.getString("K0032")); //$NON-NLS-1$
        }
        checkConnectPermission(destAddr.getHostName(), dstPort);
    }

    /*
     * Checks the connection destination satisfies the security policy.
     *
     * @param hostname the destination hostname @param dstPort the port on the
     * destination host
     */
    private void checkConnectPermission(String hostname, int dstPort) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkConnect(hostname, dstPort);
        }
    }

    /**
     * Close the socket. It is not valid to use the socket thereafter.
     *
     * @throws IOException
     *             if an error occurs during the close
     */
    public synchronized void close() throws IOException {
        isClosed = true;
        impl.close();
    }

    /**
     * Returns an {@link InetAddress} instance representing the address this
     * socket has connected to.
     *
     * @return if this socket is connected, the address it is connected to. A
     *         <code>null</code> return signifies no connection has been made.
     */
    public InetAddress getInetAddress() {
        if (!isConnected()) {
            return null;
        }
        return impl.getInetAddress();
    }

    /**
     * Answer the socket input stream, to read byte data off the socket. Note,
     * multiple input streams may be created on a single socket.
     *
     * @return a byte oriented read stream for this socket
     *
     * @throws IOException
     *             if an error occurs creating the stream
     *
     * @see org.apache.harmony.luni.net.SocketInputStream
     */
    public InputStream getInputStream() throws IOException {
        checkClosedAndCreate(false);
        if (isInputShutdown()) {
            throw new SocketException(Msg.getString("K0321")); //$NON-NLS-1$
        }
        return impl.getInputStream();
    }

    /**
     * Answer the SO_KEEPALIVE option for this socket.
     *
     * @return the socket SO_KEEPALIVE option setting
     *
     * @throws SocketException
     *             if an error occurs on the option access
     */
    public boolean getKeepAlive() throws SocketException {
        checkClosedAndCreate(true);
        return ((Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE))
                .booleanValue();
    }

    /**
     * Returns an {@link InetAddress} instance representing the <i>local</i>
     * address this socket is bound to.
     *
     * @return the local address that this socket has bound to
     */
    public InetAddress getLocalAddress() {
        if (!isBound()) {
            return InetAddress.ANY;
        }
        return Platform.getNetworkSystem().getSocketLocalAddress(impl.fd,
                InetAddress.preferIPv6Addresses());
    }

    /**
     * Answer the local port to which the socket is bound.
     *
     * @return the local port to which the socket is bound
     */
    public int getLocalPort() {
        if (!isBound()) {
            return -1;
        }
        return impl.getLocalPort();
    }

    /**
     * Answer the socket output stream, for writing byte data on the socket.
     * Note, multiplie output streams may be created on a single socket.
     *
     * @return OutputStream a byte oriented write stream for this socket
     *
     * @throws IOException
     *             if an error occurs creating the stream
     *
     * @see org.apache.harmony.luni.net.SocketOutputStream
     */
    public OutputStream getOutputStream() throws IOException {
        checkClosedAndCreate(false);
        if (isOutputShutdown()) {
            throw new SocketException(Msg.getString("KA00f")); //$NON-NLS-1$
        }
        return impl.getOutputStream();
    }

    /**
     * Returns the number of the remote port this socket is connected to.
     *
     * @return int the remote port number that this socket has connected to. A
     *         return of <code>0</code> (zero) indicates that there is no
     *         connection in place.
     */
    public int getPort() {
        if (!isConnected()) {
            return 0;
        }
        return impl.getPort();
    }

    /**
     * Answer the linger-on-close timeout for this socket (the SO_LINGER value).
     *
     * @return this socket's SO_LINGER value. A value of <code>-1</code> will
     *         be returned if the option is not enabled.
     *
     * @throws SocketException
     *             if an error occurs on querying this property
     */
    public int getSoLinger() throws SocketException {
        checkClosedAndCreate(true);
        return ((Integer) impl.getOption(SocketOptions.SO_LINGER)).intValue();
    }

    /**
     * Answer the socket receive buffer size (SO_RCVBUF).
     *
     * @return socket receive buffer size
     *
     * @throws SocketException
     *             if an error occurs on the option access
     */
    public synchronized int getReceiveBufferSize() throws SocketException {
        checkClosedAndCreate(true);
        return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
    }

    /**
     * Answer the socket send buffer size (SO_SNDBUF).
     *
     * @return socket send buffer size
     *
     * @throws SocketException
     *             if an error occurs on the option access
     */
    public synchronized int getSendBufferSize() throws SocketException {
        checkClosedAndCreate(true);
        return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
    }

    /**
     * Answer the socket read timeout. The SO_TIMEOUT option, a value of 0
     * indicates it is disabled and a read operation will block indefinitely
     * waiting for data.
     *
     * @return the socket read timeout
     *
     * @throws SocketException
     *             if an error occurs on the option access
     */
    public synchronized int getSoTimeout() throws SocketException {
        checkClosedAndCreate(true);
        return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
    }

    /**
     * Answer true if the socket is using Nagle's algorithm. The TCP_NODELAY
     * option setting.
     *
     * @return the socket TCP_NODELAY option setting
     *
     * @throws SocketException
     *             if an error occurs on the option access
     */
    public boolean getTcpNoDelay() throws SocketException {
        checkClosedAndCreate(true);
        return ((Boolean) impl.getOption(SocketOptions.TCP_NODELAY))
                .booleanValue();
    }

    /**
     * Set the SO_KEEPALIVE option for this socket.
     *
     * @param value
     *            the socket SO_KEEPALIVE option setting
     *
     * @throws SocketException
     *             if an error occurs setting the option
     */
    public void setKeepAlive(boolean value) throws SocketException {
        if (impl != null) {
            checkClosedAndCreate(true);
            impl.setOption(SocketOptions.SO_KEEPALIVE, value ? Boolean.TRUE
                    : Boolean.FALSE);
        }
    }

    /**
     * Specifies the application's socket implementation factory. This may only
     * be executed the once over the lifetime of the application.
     *
     * @param fac
     *            the socket factory to set
     * @exception IOException
     *                thrown if the factory has already been set
     */
    public static synchronized void setSocketImplFactory(SocketImplFactory fac)
            throws IOException {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkSetFactory();
        }
        if (factory != null) {
            throw new SocketException(Msg.getString("K0044")); //$NON-NLS-1$
        }
        factory = fac;
    }

    /**
     * Set the socket send buffer size.
     *
     * @param size
     *            the buffer size, in bytes
     *
     * @throws SocketException
     *             if an error occurs while setting the size or the size is
     *             invalid.
     */
    public synchronized void setSendBufferSize(int size) throws SocketException {
        checkClosedAndCreate(true);
        if (size < 1) {
            throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
        }
        impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
    }

    /**
     * Set the socket receive buffer size.
     *
     * @param size
     *            the buffer size, in bytes
     *
     * @throws SocketException
     *             tf an error occurs while setting the size or the size is
     *             invalid.
     */
    public synchronized void setReceiveBufferSize(int size)
            throws SocketException {
        checkClosedAndCreate(true);
        if (size < 1) {
            throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
        }
        impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
    }

    /**
     * Set the SO_LINGER option, with the specified time, in seconds. The
     * SO_LINGER option is silently limited to 65535 seconds.
     *
     * @param on
     *            if linger is enabled
     * @param timeout
     *            the linger timeout value, in seconds
     *
     * @throws SocketException
     *             if an error occurs setting the option
     */
    public void setSoLinger(boolean on, int timeout) throws SocketException {
        checkClosedAndCreate(true);
        if (on && timeout < 0) {
            throw new IllegalArgumentException(Msg.getString("K0045")); //$NON-NLS-1$
        }
        int val = on ? (65535 < timeout ? 65535 : timeout) : -1;
        impl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(val));
    }

    /**
     * Set the read timeout on this socket. The SO_TIMEOUT option, is specified
     * in milliseconds. The read operation will block indefinitely for a zero
     * value.
     *
     * @param timeout
     *            the read timeout value
     *
     * @throws SocketException
     *             if an error occurs setting the option
     */
    public synchronized void setSoTimeout(int timeout) throws SocketException {
        checkClosedAndCreate(true);
        if (timeout < 0) {
            throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$
        }
        impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
    }

    /**
     * Set whether the socket is to use Nagle's algorithm. The TCP_NODELAY
     * option setting.
     *
     * @param on
     *            the socket TCP_NODELAY option setting
     *
     * @throws SocketException
     *             if an error occurs setting the option
     */
    public void setTcpNoDelay(boolean on) throws SocketException {
        checkClosedAndCreate(true);
        impl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
    }

    /**
     * Creates a stream socket, binds it to the nominated local address/port,
     * then connects it to the nominated destination address/port.
     *
     * @param dstAddress
     *            the destination host address
     * @param dstPort
     *            the port on the destination host
     * @param localAddress
     *            the address on the local machine to bind
     * @param localPort
     *            the port on the local machine to bind
     *
     * @throws IOException
     *             thrown if a error occurs during the bind or connect
     *             operations
     */
    void startupSocket(InetAddress dstAddress, int dstPort,
            InetAddress localAddress, int localPort, boolean streaming)
            throws IOException {

        if (localPort < 0 || localPort > 65535) {
            throw new IllegalArgumentException(Msg.getString("K0046")); //$NON-NLS-1$
        }

        InetAddress addr = localAddress == null ? InetAddress.ANY
                : localAddress;
        synchronized (this) {
            impl.create(streaming);
            isCreated = true;
            try {
                if (!streaming || !NetUtil.usingSocks(proxy)) {
                    impl.bind(addr, localPort);
                }
                isBound = true;
                impl.connect(dstAddress, dstPort);
                isConnected = true;
            } catch (IOException e) {
                impl.close();
                throw e;
            }
        }
    }

    /**
     * Answers a string containing a concise, human-readable description of the
     * socket.
     *
     * @return the description
     */
    @Override
    public String toString() {
        if (!isConnected()) {
            return "Socket[unconnected]"; //$NON-NLS-1$
        }
        return impl.toString();
    }

    /**
     * Shutdown the input portion of the socket.
     *
     * @throws IOException
     *             if an error occurs while closing the socket input
     * @throws SocketException
     *             if the socket is closed
     */
    public void shutdownInput() throws IOException {
        if (isInputShutdown()) {
            throw new SocketException(Msg.getString("K0321")); //$NON-NLS-1$
        }
        checkClosedAndCreate(false);
        impl.shutdownInput();
        isInputShutdown = true;
    }

    /**
     * Shutdown the output portion of the socket.
     *
     * @throws IOException
     *             if an error occurs while closing the socket output
     * @throws SocketException
     *             if the socket is closed
     */
    public void shutdownOutput() throws IOException {
        if (isOutputShutdown()) {
            throw new SocketException(Msg.getString("KA00f")); //$NON-NLS-1$
        }
        checkClosedAndCreate(false);
        impl.shutdownOutput();
        isOutputShutdown = true;
    }

    /**
     * Check if the socket is closed, and throw an exception. Otherwise create
     * the underlying SocketImpl.
     *
     * @throws SocketException
     *             if the socket is closed
     */
    private void checkClosedAndCreate(boolean create) throws SocketException {
        if (isClosed()) {
            throw new SocketException(Msg.getString("K003d")); //$NON-NLS-1$
        }
        if (!create) {
            if (!isConnected()) {
                throw new SocketException(Msg.getString("K0320")); //$NON-NLS-1$
                // a connected socket must be created
            }

            /*
             * return directly to fix a possible bug, if !create, should return
             * here
             */
            return;
        }
        if (isCreated) {
            return;
        }
        synchronized (this) {
            if (isCreated) {
                return;
            }
            try {
                impl.create(true);
            } catch (SocketException e) {
                throw e;
            } catch (IOException e) {
                throw new SocketException(e.toString());
            }
            isCreated = true;
        }
    }

    /**
     * Answer the local SocketAddress for this socket, or null if the socket is
     * not bound.
     * <p>
     * This is useful on multihomed hosts.
     *
     * @return the local socket address
     */
    public SocketAddress getLocalSocketAddress() {
        if (!isBound()) {
            return null;
        }
        return new InetSocketAddress(getLocalAddress(), getLocalPort());
    }

    /**
     * Answer the remote SocketAddress for this socket, or null if the socket is
     * not connected.
     *
     * @return the remote socket address
     */
    public SocketAddress getRemoteSocketAddress() {
        if (!isConnected()) {
            return null;
        }
        return new InetSocketAddress(getInetAddress(), getPort());
    }

    /**
     * Return if the socket is bound to a local address and port.
     *
     * @return <code>true</code> if the socket is bound to a local address,
     *         <code>false</code> otherwise.
     */
    public boolean isBound() {
        return isBound;
    }

    /**
     * Return if the socket is connected.
     *
     * @return <code>true</code> if the socket is connected,
     *         <code>false</code> otherwise.
     */
    public boolean isConnected() {
        return isConnected;
    }

    /**
     * Return if the socket is closed.
     *
     * @return <code>true</code> if the socket is closed, <code>false</code>
     *         otherwise.
     */
    public boolean isClosed() {
        return isClosed;
    }

    /**
     * Bind the Socket to the nominated local host/port.
     *
     * @param localAddr
     *            the local machine address and port to bind on
     *
     * @throws IllegalArgumentException
     *             if the SocketAddress is not supported
     * @throws IOException
     *             if the socket is already bound, or a problem occurs during
     *             the bind
     */
    public void bind(SocketAddress localAddr) throws IOException {
        checkClosedAndCreate(true);
        if (isBound()) {
            throw new BindException(Msg.getString("K0315")); //$NON-NLS-1$
        }

        int port = 0;
        InetAddress addr = InetAddress.ANY;
        if (localAddr != null) {
            if (!(localAddr instanceof InetSocketAddress)) {
                throw new IllegalArgumentException(Msg.getString(
                        "K0316", localAddr.getClass())); //$NON-NLS-1$
            }
            InetSocketAddress inetAddr = (InetSocketAddress) localAddr;
            if ((addr = inetAddr.getAddress()) == null) {
                throw new SocketException(Msg.getString(
                        "K0317", inetAddr.getHostName())); //$NON-NLS-1$
            }
            port = inetAddr.getPort();
        }

        synchronized (this) {
            try {
                impl.bind(addr, port);
                isBound = true;
            } catch (IOException e) {
                impl.close();
                throw e;
            }
        }
    }

    /**
     * Connect the Socket to the host/port specified by the SocketAddress.
     *
     * @param remoteAddr
     *            the remote machine address and port to connect to
     *
     * @throws IllegalArgumentException
     *             if the SocketAddress is not supported
     * @throws IOException
     *             if the socket is already connected, or a problem occurs
     *             during the connect
     */
    public void connect(SocketAddress remoteAddr) throws IOException {
        connect(remoteAddr, 0);
    }

    /**
     * Connect the Socket to the host/port specified by the SocketAddress with a
     * specified timeout.
     *
     * @param remoteAddr
     *            the remote machine address and port to connect to
     * @param timeout
     *            the millisecond timeout value, the connect will block
     *            indefinitely for a zero value.
     *
     * @throws IllegalArgumentException
     *             if the timeout is negative, or the SocketAddress is not
     *             supported
     * @throws IOException
     *             if the socket is already connected, or a problem occurs
     *             during the connect
     */
    public void connect(SocketAddress remoteAddr, int timeout)
            throws IOException {
        checkClosedAndCreate(true);
        if (timeout < 0) {
            throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$
        }
        if (isConnected()) {
            throw new SocketException(Msg.getString("K0079")); //$NON-NLS-1$
        }
        if (remoteAddr == null) {
            throw new IllegalArgumentException(Msg.getString("K0318")); //$NON-NLS-1$
        }

        if (!(remoteAddr instanceof InetSocketAddress)) {
            throw new IllegalArgumentException(Msg.getString(
                    "K0316", remoteAddr.getClass())); //$NON-NLS-1$
        }
        InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr;
        InetAddress addr;
        if ((addr = inetAddr.getAddress()) == null) {
            throw new UnknownHostException(Msg.getString("K0317", remoteAddr));//$NON-NLS-1$
        }
        int port = inetAddr.getPort();

        checkDestination(addr, port);
        synchronized (connectLock) {
            try {
                if (!isBound()) {
                    // socket allready created at this point by earlier call or
                    // checkClosedAndCreate this caused us to lose socket
                    // options on create
                    // impl.create(true);
                    if (!NetUtil.usingSocks(proxy)) {
                        impl.bind(InetAddress.ANY, 0);
                    }
                    isBound = true;
                }
                impl.connect(remoteAddr, timeout);
                isConnected = true;
            } catch (IOException e) {
                impl.close();
                throw e;
            }
        }
    }

    /**
     * Return if {@link #shutdownInput} has been called.
     *
     * @return <code>true</code> if <code>shutdownInput</code> has been
     *         called, <code>false</code> otherwise.
     */
    public boolean isInputShutdown() {
        return isInputShutdown;
    }

    /**
     * Return if {@link #shutdownOutput} has been called.
     *
     * @return <code>true</code> if <code>shutdownOutput</code> has been
     *         called, <code>false</code> otherwise.
     */
    public boolean isOutputShutdown() {
        return isOutputShutdown;
    }

    /**
     * Set the SO_REUSEADDR socket option.
     *
     * @param reuse
     *            the socket SO_REUSEADDR option setting
     *
     * @throws SocketException
     *             if the socket is closed or the option is invalid.
     */
    public void setReuseAddress(boolean reuse) throws SocketException {
        checkClosedAndCreate(true);
        impl.setOption(SocketOptions.SO_REUSEADDR, reuse ? Boolean.TRUE
                : Boolean.FALSE);
    }

    /**
     * Get the state of the SO_REUSEADDR socket option.
     *
     * @return <code>true</code> if the SO_REUSEADDR is enabled,
     *         <code>false</code> otherwise.
     *
     * @throws SocketException
     *             if the socket is closed or the option is invalid.
     */
    public boolean getReuseAddress() throws SocketException {
        checkClosedAndCreate(true);
        return ((Boolean) impl.getOption(SocketOptions.SO_REUSEADDR))
                .booleanValue();
    }

    /**
     * Set the SO_OOBINLINE socket option. When this option is enabled, out of
     * band data is recieved in the normal data stream.
     *
     * @param oobinline
     *            the socket SO_OOBINLINE option setting
     *
     * @throws SocketException
     *             if the socket is closed or the option is invalid.
     */
    public void setOOBInline(boolean oobinline) throws SocketException {
        checkClosedAndCreate(true);
        impl.setOption(SocketOptions.SO_OOBINLINE, oobinline ? Boolean.TRUE
                : Boolean.FALSE);
    }

    /**
     * Get the state of the SO_OOBINLINE socket option.
     *
     * @return <code>true</code> if the SO_OOBINLINE is enabled,
     *         <code>false</code> otherwise.
     *
     * @throws SocketException
     *             if the socket is closed or the option is invalid.
     */
    public boolean getOOBInline() throws SocketException {
        checkClosedAndCreate(true);
        return ((Boolean) impl.getOption(SocketOptions.SO_OOBINLINE))
                .booleanValue();
    }

    /**
     * Set the IP_TOS socket option.
     *
     * @param value
     *            the socket IP_TOS setting
     *
     * @throws SocketException
     *             if the socket is closed or the option is invalid.
     */
    public void setTrafficClass(int value) throws SocketException {
        checkClosedAndCreate(true);
        if (value < 0 || value > 255) {
            throw new IllegalArgumentException();
        }
        impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
    }

    /**
     * Get the IP_TOS socket option.
     *
     * @return the IP_TOS socket option value
     *
     * @throws SocketException
     *             if the option is invalid
     */
    public int getTrafficClass() throws SocketException {
        checkClosedAndCreate(true);
        return ((Number) impl.getOption(SocketOptions.IP_TOS)).intValue();
    }

    /**
     * Send the single byte of urgent data on the socket.
     *
     * @param value
     *            the byte of urgent data
     *
     * @exception IOException
     *                when an error occurs sending urgent data
     */
    public void sendUrgentData(int value) throws IOException {
        if (!impl.supportsUrgentData()) {
            throw new SocketException(Msg.getString("K0333")); //$NON-NLS-1$
        }
        impl.sendUrgentData(value);
    }

    /**
     * Set the appropriate flags for a Socket created by ServerSocket.accept().
     *
     * @see ServerSocket#implAccept
     */
    void accepted() {
        isCreated = isBound = isConnected = true;
    }

    static boolean preferIPv4Stack() {
        String result = AccessController.doPrivileged(new PriviAction<String>(
                "java.net.preferIPv4Stack")); //$NON-NLS-1$
        return "true".equals(result); //$NON-NLS-1$
    }

    /**
     * if Socket is created by a SocketChannel, returns the related
     * SocketChannel
     *
     * @return the related SocketChannel
     */
    public SocketChannel getChannel() {
        return null;
    }

    /**
     * sets performance preference for connectionTime,latency and bandwidth
     *
     * @param connectionTime
     *            the importance of connect time
     * @param latency
     *            the importance of latency
     * @param bandwidth
     *            the importance of bandwidth
     */
    public void setPerformancePreferences(int connectionTime, int latency,
            int bandwidth) {
        // Our socket implementation only provide one protocol: TCP/IP, so
        // we do nothing for this method
    }
}
TOP

Related Classes of java.net.Socket$ConnectLock

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.