/luni/src/main/java/java/net/Socket.java
Java | 989 lines | 424 code | 74 blank | 491 comment | 62 complexity | 60a9c775280f16706fbdabbd067ce5b5 MD5 | raw file
- /*
- * 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.FileDescriptor;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.nio.channels.SocketChannel;
- import libcore.io.IoBridge;
- /**
- * Provides a client-side TCP socket.
- */
- public class Socket {
- private static SocketImplFactory factory;
- final SocketImpl impl;
- private final Proxy proxy;
- 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 InetAddress localAddress = Inet4Address.ANY;
- private final Object connectLock = new Object();
- /**
- * Creates a new unconnected socket. When a SocketImplFactory is defined it
- * creates the internal socket implementation, otherwise the default socket
- * implementation will be used for this socket.
- *
- * @see SocketImplFactory
- * @see SocketImpl
- */
- public Socket() {
- this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl();
- this.proxy = null;
- }
- /**
- * Creates a new unconnected socket using the given proxy type. When a
- * {@code SocketImplFactory} is defined it creates the internal socket
- * implementation, otherwise the default socket implementation will be used
- * for this socket.
- * <p>
- * Example that will create a socket connection through a {@code SOCKS}
- * proxy server: <br>
- * {@code Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new
- * InetSocketAddress("test.domain.org", 2130)));}
- *
- * @param proxy
- * the specified proxy for this socket.
- * @throws IllegalArgumentException
- * if the argument {@code proxy} is {@code null} or of an
- * invalid type.
- * @see SocketImplFactory
- * @see SocketImpl
- */
- public Socket(Proxy proxy) {
- if (proxy == null || proxy.type() == Proxy.Type.HTTP) {
- throw new IllegalArgumentException("Invalid proxy: " + proxy);
- }
- this.proxy = proxy;
- this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl(proxy);
- }
- /**
- * Tries to connect a socket to all IP addresses of the given hostname.
- *
- * @param dstName
- * the target host name or IP address to connect to.
- * @param dstPort
- * the port on the target host to connect to.
- * @param localAddress
- * the address on the local host to bind to.
- * @param localPort
- * the port on the local host to bind to.
- * @param streaming
- * if {@code true} a streaming socket is returned, a datagram
- * socket otherwise.
- * @throws UnknownHostException
- * if the host name could not be resolved into an IP address.
- * @throws IOException
- * if an error occurs while creating the socket.
- */
- private void tryAllAddresses(String dstName, int dstPort, InetAddress
- localAddress, int localPort, boolean streaming) throws IOException {
- InetAddress[] dstAddresses = InetAddress.getAllByName(dstName);
- // Loop through all the destination addresses except the last, trying to
- // connect to each one and ignoring errors. There must be at least one
- // address, or getAllByName would have thrown UnknownHostException.
- InetAddress dstAddress;
- for (int i = 0; i < dstAddresses.length - 1; i++) {
- dstAddress = dstAddresses[i];
- try {
- checkDestination(dstAddress, dstPort);
- startupSocket(dstAddress, dstPort, localAddress, localPort, streaming);
- return;
- } catch (IOException ex) {
- }
- }
- // Now try to connect to the last address in the array, handing back to
- // the caller any exceptions that are thrown.
- dstAddress = dstAddresses[dstAddresses.length - 1];
- checkDestination(dstAddress, dstPort);
- startupSocket(dstAddress, dstPort, localAddress, localPort, streaming);
- }
- /**
- * Creates a new streaming socket connected to the target host specified by
- * the parameters {@code dstName} and {@code dstPort}. The socket is bound
- * to any available port on the local host.
- *
- * <p>This implementation tries each IP address for the given hostname (in
- * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
- * until it either connects successfully or it exhausts the set.
- *
- * @param dstName
- * the target host name or IP address to connect to.
- * @param dstPort
- * the port on the target host to connect to.
- * @throws UnknownHostException
- * if the host name could not be resolved into an IP address.
- * @throws IOException
- * if an error occurs while creating the socket.
- */
- public Socket(String dstName, int dstPort) throws UnknownHostException, IOException {
- this(dstName, dstPort, null, 0);
- }
- /**
- * Creates a new streaming socket connected to the target host specified by
- * the parameters {@code dstName} and {@code dstPort}. On the local endpoint
- * the socket is bound to the given address {@code localAddress} on port
- * {@code localPort}. If {@code host} is {@code null} a loopback address is used to connect to.
- *
- * <p>This implementation tries each IP address for the given hostname (in
- * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
- * until it either connects successfully or it exhausts the set.
- *
- * @param dstName
- * the target host name or IP address to connect to.
- * @param dstPort
- * the port on the target host to connect to.
- * @param localAddress
- * the address on the local host to bind to.
- * @param localPort
- * the port on the local host to bind to.
- * @throws UnknownHostException
- * if the host name could not be resolved into an IP address.
- * @throws IOException
- * if an error occurs while creating the socket.
- */
- public Socket(String dstName, int dstPort, InetAddress localAddress, int localPort) throws IOException {
- this();
- tryAllAddresses(dstName, dstPort, localAddress, localPort, true);
- }
- /**
- * Creates a new streaming or datagram socket connected to the target host
- * specified by the parameters {@code hostName} and {@code port}. The socket
- * is bound to any available port on the local host.
- *
- * <p>This implementation tries each IP address for the given hostname (in
- * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
- * until it either connects successfully or it exhausts the set.
- *
- * @param hostName
- * the target host name or IP address to connect to.
- * @param port
- * the port on the target host to connect to.
- * @param streaming
- * if {@code true} a streaming socket is returned, a datagram
- * socket otherwise.
- * @throws UnknownHostException
- * if the host name could not be resolved into an IP address.
- * @throws IOException
- * if an error occurs while creating the socket.
- * @deprecated Use {@code Socket(String, int)} instead of this for streaming
- * sockets or an appropriate constructor of {@code
- * DatagramSocket} for UDP transport.
- */
- @Deprecated
- public Socket(String hostName, int port, boolean streaming) throws IOException {
- this();
- tryAllAddresses(hostName, port, null, 0, streaming);
- }
- /**
- * Creates a new streaming socket connected to the target host specified by
- * the parameters {@code dstAddress} and {@code dstPort}. The socket is
- * bound to any available port on the local host.
- *
- * @param dstAddress
- * the target host address to connect to.
- * @param dstPort
- * the port on the target host to connect to.
- * @throws IOException
- * if an error occurs while creating the socket.
- */
- public Socket(InetAddress dstAddress, int dstPort) throws IOException {
- this();
- checkDestination(dstAddress, dstPort);
- startupSocket(dstAddress, dstPort, null, 0, true);
- }
- /**
- * Creates a new streaming socket connected to the target host specified by
- * the parameters {@code dstAddress} and {@code dstPort}. On the local
- * endpoint the socket is bound to the given address {@code localAddress} on
- * port {@code localPort}.
- *
- * @param dstAddress
- * the target host address to connect to.
- * @param dstPort
- * the port on the target host to connect to.
- * @param localAddress
- * the address on the local host to bind to.
- * @param localPort
- * the port on the local host to bind to.
- * @throws IOException
- * if an error occurs while creating the socket.
- */
- public Socket(InetAddress dstAddress, int dstPort,
- InetAddress localAddress, int localPort) throws IOException {
- this();
- checkDestination(dstAddress, dstPort);
- startupSocket(dstAddress, dstPort, localAddress, localPort, true);
- }
- /**
- * Creates a new streaming or datagram socket connected to the target host
- * specified by the parameters {@code addr} and {@code port}. The socket is
- * bound to any available port on the local host.
- *
- * @param addr
- * the Internet address to connect to.
- * @param port
- * the port on the target host to connect to.
- * @param streaming
- * if {@code true} a streaming socket is returned, a datagram
- * socket otherwise.
- * @throws IOException
- * if an error occurs while creating the socket.
- * @deprecated Use {@code Socket(InetAddress, int)} instead of this for
- * streaming sockets or an appropriate constructor of {@code
- * DatagramSocket} for UDP transport.
- */
- @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 with the given socket implementation.
- *
- * @param impl
- * the socket implementation to be used.
- * @throws SocketException
- * if an error occurs while creating the socket.
- */
- protected Socket(SocketImpl impl) throws SocketException {
- this.impl = impl;
- this.proxy = null;
- }
- /**
- * Checks whether the connection destination satisfies the security policy
- * and the validity of the port range.
- *
- * @param destAddr
- * the destination host address.
- * @param dstPort
- * the port on the destination host.
- */
- private void checkDestination(InetAddress destAddr, int dstPort) {
- if (dstPort < 0 || dstPort > 65535) {
- throw new IllegalArgumentException("Port out of range: " + dstPort);
- }
- }
- /**
- * Closes the socket. It is not possible to reconnect or rebind to this
- * socket thereafter which means a new socket instance has to be created.
- *
- * @throws IOException
- * if an error occurs while closing the socket.
- */
- public synchronized void close() throws IOException {
- isClosed = true;
- // RI compatibility: the RI returns the any address (but the original local port) after close.
- localAddress = Inet4Address.ANY;
- impl.close();
- }
- /**
- * Returns the IP address of the target host this socket is connected to, or null if this
- * socket is not yet connected.
- */
- public InetAddress getInetAddress() {
- if (!isConnected()) {
- return null;
- }
- return impl.getInetAddress();
- }
- /**
- * Returns an input stream to read data from this socket.
- *
- * @return the byte-oriented input stream.
- * @throws IOException
- * if an error occurs while creating the input stream or the
- * socket is in an invalid state.
- */
- public InputStream getInputStream() throws IOException {
- checkOpenAndCreate(false);
- if (isInputShutdown()) {
- throw new SocketException("Socket input is shutdown");
- }
- return impl.getInputStream();
- }
- /**
- * Returns this socket's {@link SocketOptions#SO_KEEPALIVE} setting.
- */
- public boolean getKeepAlive() throws SocketException {
- checkOpenAndCreate(true);
- return (Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE);
- }
- /**
- * Returns the local IP address this socket is bound to, or {@code InetAddress.ANY} if
- * the socket is unbound.
- */
- public InetAddress getLocalAddress() {
- return localAddress;
- }
- /**
- * Returns the local port this socket is bound to, or -1 if the socket is unbound.
- */
- public int getLocalPort() {
- if (!isBound()) {
- return -1;
- }
- return impl.getLocalPort();
- }
- /**
- * Returns an output stream to write data into this socket.
- *
- * @return the byte-oriented output stream.
- * @throws IOException
- * if an error occurs while creating the output stream or the
- * socket is in an invalid state.
- */
- public OutputStream getOutputStream() throws IOException {
- checkOpenAndCreate(false);
- if (isOutputShutdown()) {
- throw new SocketException("Socket output is shutdown");
- }
- return impl.getOutputStream();
- }
- /**
- * Returns the port number of the target host this socket is connected to, or 0 if this socket
- * is not yet connected.
- */
- public int getPort() {
- if (!isConnected()) {
- return 0;
- }
- return impl.getPort();
- }
- /**
- * Returns this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds, or -1
- * for no linger (i.e. {@code close} will return immediately).
- */
- public int getSoLinger() throws SocketException {
- checkOpenAndCreate(true);
- // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
- Object value = impl.getOption(SocketOptions.SO_LINGER);
- if (value instanceof Integer) {
- return (Integer) value;
- } else {
- return -1;
- }
- }
- /**
- * Returns this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
- */
- public synchronized int getReceiveBufferSize() throws SocketException {
- checkOpenAndCreate(true);
- return (Integer) impl.getOption(SocketOptions.SO_RCVBUF);
- }
- /**
- * Returns this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
- */
- public synchronized int getSendBufferSize() throws SocketException {
- checkOpenAndCreate(true);
- return (Integer) impl.getOption(SocketOptions.SO_SNDBUF);
- }
- /**
- * Returns this socket's {@link SocketOptions#SO_TIMEOUT receive timeout}.
- */
- public synchronized int getSoTimeout() throws SocketException {
- checkOpenAndCreate(true);
- return (Integer) impl.getOption(SocketOptions.SO_TIMEOUT);
- }
- /**
- * Returns this socket's {@code SocketOptions#TCP_NODELAY} setting.
- */
- public boolean getTcpNoDelay() throws SocketException {
- checkOpenAndCreate(true);
- return (Boolean) impl.getOption(SocketOptions.TCP_NODELAY);
- }
- /**
- * Sets this socket's {@link SocketOptions#SO_KEEPALIVE} option.
- */
- public void setKeepAlive(boolean keepAlive) throws SocketException {
- if (impl != null) {
- checkOpenAndCreate(true);
- impl.setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(keepAlive));
- }
- }
- /**
- * Sets the internal factory for creating socket implementations. This may
- * only be executed once during the lifetime of the application.
- *
- * @param fac
- * the socket implementation factory to be set.
- * @throws IOException
- * if the factory has been already set.
- */
- public static synchronized void setSocketImplFactory(SocketImplFactory fac)
- throws IOException {
- if (factory != null) {
- throw new SocketException("Factory already set");
- }
- factory = fac;
- }
- /**
- * Sets this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
- */
- public synchronized void setSendBufferSize(int size) throws SocketException {
- checkOpenAndCreate(true);
- if (size < 1) {
- throw new IllegalArgumentException("size < 1");
- }
- impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
- }
- /**
- * Sets this socket's {@link SocketOptions#SO_SNDBUF receive buffer size}.
- */
- public synchronized void setReceiveBufferSize(int size) throws SocketException {
- checkOpenAndCreate(true);
- if (size < 1) {
- throw new IllegalArgumentException("size < 1");
- }
- impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
- }
- /**
- * Sets this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds.
- * If {@code on} is false, {@code timeout} is irrelevant.
- */
- public void setSoLinger(boolean on, int timeout) throws SocketException {
- checkOpenAndCreate(true);
- // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
- if (on && timeout < 0) {
- throw new IllegalArgumentException("timeout < 0");
- }
- if (on) {
- impl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(timeout));
- } else {
- impl.setOption(SocketOptions.SO_LINGER, Boolean.FALSE);
- }
- }
- /**
- * Sets this socket's {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds.
- * Use 0 for no timeout.
- * To take effect, this option must be set before the blocking method was called.
- */
- public synchronized void setSoTimeout(int timeout) throws SocketException {
- checkOpenAndCreate(true);
- if (timeout < 0) {
- throw new IllegalArgumentException("timeout < 0");
- }
- impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
- }
- /**
- * Sets this socket's {@link SocketOptions#TCP_NODELAY} option.
- */
- public void setTcpNoDelay(boolean on) throws SocketException {
- checkOpenAndCreate(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 an error occurs during the bind or connect
- * operations.
- */
- private void startupSocket(InetAddress dstAddress, int dstPort,
- InetAddress localAddress, int localPort, boolean streaming)
- throws IOException {
- if (localPort < 0 || localPort > 65535) {
- throw new IllegalArgumentException("Local port out of range: " + localPort);
- }
- InetAddress addr = localAddress == null ? Inet4Address.ANY : localAddress;
- synchronized (this) {
- impl.create(streaming);
- isCreated = true;
- try {
- if (!streaming || !usingSocks()) {
- impl.bind(addr, localPort);
- }
- isBound = true;
- impl.connect(dstAddress, dstPort);
- isConnected = true;
- cacheLocalAddress();
- } catch (IOException e) {
- impl.close();
- throw e;
- }
- }
- }
- private boolean usingSocks() {
- return proxy != null && proxy.type() == Proxy.Type.SOCKS;
- }
- /**
- * Returns a {@code String} containing a concise, human-readable description of the
- * socket.
- *
- * @return the textual representation of this socket.
- */
- @Override
- public String toString() {
- if (!isConnected()) {
- return "Socket[unconnected]";
- }
- return impl.toString();
- }
- /**
- * Closes the input stream of this socket. Any further data sent to this
- * socket will be discarded. Reading from this socket after this method has
- * been called will return the value {@code EOF}.
- *
- * @throws IOException
- * if an error occurs while closing the socket input stream.
- * @throws SocketException
- * if the input stream is already closed.
- */
- public void shutdownInput() throws IOException {
- if (isInputShutdown()) {
- throw new SocketException("Socket input is shutdown");
- }
- checkOpenAndCreate(false);
- impl.shutdownInput();
- isInputShutdown = true;
- }
- /**
- * Closes the output stream of this socket. All buffered data will be sent
- * followed by the termination sequence. Writing to the closed output stream
- * will cause an {@code IOException}.
- *
- * @throws IOException
- * if an error occurs while closing the socket output stream.
- * @throws SocketException
- * if the output stream is already closed.
- */
- public void shutdownOutput() throws IOException {
- if (isOutputShutdown()) {
- throw new SocketException("Socket output is shutdown");
- }
- checkOpenAndCreate(false);
- impl.shutdownOutput();
- isOutputShutdown = true;
- }
- /**
- * Checks whether the socket is closed, and throws an exception. Otherwise
- * creates the underlying SocketImpl.
- *
- * @throws SocketException
- * if the socket is closed.
- */
- private void checkOpenAndCreate(boolean create) throws SocketException {
- if (isClosed()) {
- throw new SocketException("Socket is closed");
- }
- if (!create) {
- if (!isConnected()) {
- throw new SocketException("Socket is not connected");
- // 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;
- }
- }
- /**
- * Returns the local address and port of this socket as a SocketAddress or
- * null if the socket is unbound. This is useful on multihomed
- * hosts.
- */
- public SocketAddress getLocalSocketAddress() {
- if (!isBound()) {
- return null;
- }
- return new InetSocketAddress(getLocalAddress(), getLocalPort());
- }
- /**
- * Returns the remote address and port of this socket as a {@code
- * SocketAddress} or null if the socket is not connected.
- *
- * @return the remote socket address and port.
- */
- public SocketAddress getRemoteSocketAddress() {
- if (!isConnected()) {
- return null;
- }
- return new InetSocketAddress(getInetAddress(), getPort());
- }
- /**
- * Returns whether this socket is bound to a local address and port.
- *
- * @return {@code true} if the socket is bound to a local address, {@code
- * false} otherwise.
- */
- public boolean isBound() {
- return isBound;
- }
- /**
- * Returns whether this socket is connected to a remote host.
- *
- * @return {@code true} if the socket is connected, {@code false} otherwise.
- */
- public boolean isConnected() {
- return isConnected;
- }
- /**
- * Returns whether this socket is closed.
- *
- * @return {@code true} if the socket is closed, {@code false} otherwise.
- */
- public boolean isClosed() {
- return isClosed;
- }
- /**
- * Binds this socket to the given local host address and port specified by
- * the SocketAddress {@code localAddr}. If {@code localAddr} is set to
- * {@code null}, this socket will be bound to an available local address on
- * any free port.
- *
- * @param localAddr
- * the specific address and port on the local machine to bind to.
- * @throws IllegalArgumentException
- * if the given SocketAddress is invalid or not supported.
- * @throws IOException
- * if the socket is already bound or an error occurs while
- * binding.
- */
- public void bind(SocketAddress localAddr) throws IOException {
- checkOpenAndCreate(true);
- if (isBound()) {
- throw new BindException("Socket is already bound");
- }
- int port = 0;
- InetAddress addr = Inet4Address.ANY;
- if (localAddr != null) {
- if (!(localAddr instanceof InetSocketAddress)) {
- throw new IllegalArgumentException("Local address not an InetSocketAddress: " +
- localAddr.getClass());
- }
- InetSocketAddress inetAddr = (InetSocketAddress) localAddr;
- if ((addr = inetAddr.getAddress()) == null) {
- throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName());
- }
- port = inetAddr.getPort();
- }
- synchronized (this) {
- try {
- impl.bind(addr, port);
- isBound = true;
- cacheLocalAddress();
- } catch (IOException e) {
- impl.close();
- throw e;
- }
- }
- }
- /**
- * Connects this socket to the given remote host address and port specified
- * by the SocketAddress {@code remoteAddr}.
- *
- * @param remoteAddr
- * the address and port of the remote host to connect to.
- * @throws IllegalArgumentException
- * if the given SocketAddress is invalid or not supported.
- * @throws IOException
- * if the socket is already connected or an error occurs while
- * connecting.
- */
- public void connect(SocketAddress remoteAddr) throws IOException {
- connect(remoteAddr, 0);
- }
- /**
- * Connects this socket to the given remote host address and port specified
- * by the SocketAddress {@code remoteAddr} with the specified timeout. The
- * connecting method will block until the connection is established or an
- * error occurred.
- *
- * @param remoteAddr
- * the address and port of the remote host to connect to.
- * @param timeout
- * the timeout value in milliseconds or {@code 0} for an infinite
- * timeout.
- * @throws IllegalArgumentException
- * if the given SocketAddress is invalid or not supported or the
- * timeout value is negative.
- * @throws IOException
- * if the socket is already connected or an error occurs while
- * connecting.
- */
- public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
- checkOpenAndCreate(true);
- if (timeout < 0) {
- throw new IllegalArgumentException("timeout < 0");
- }
- if (isConnected()) {
- throw new SocketException("Already connected");
- }
- if (remoteAddr == null) {
- throw new IllegalArgumentException("remoteAddr == null");
- }
- if (!(remoteAddr instanceof InetSocketAddress)) {
- throw new IllegalArgumentException("Remote address not an InetSocketAddress: " +
- remoteAddr.getClass());
- }
- InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr;
- InetAddress addr;
- if ((addr = inetAddr.getAddress()) == null) {
- throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName());
- }
- int port = inetAddr.getPort();
- checkDestination(addr, port);
- synchronized (connectLock) {
- try {
- if (!isBound()) {
- // socket already created at this point by earlier call or
- // checkOpenAndCreate this caused us to lose socket
- // options on create
- // impl.create(true);
- if (!usingSocks()) {
- impl.bind(Inet4Address.ANY, 0);
- }
- isBound = true;
- }
- impl.connect(remoteAddr, timeout);
- isConnected = true;
- cacheLocalAddress();
- } catch (IOException e) {
- impl.close();
- throw e;
- }
- }
- }
- /**
- * Returns whether the incoming channel of the socket has already been
- * closed.
- *
- * @return {@code true} if reading from this socket is not possible anymore,
- * {@code false} otherwise.
- */
- public boolean isInputShutdown() {
- return isInputShutdown;
- }
- /**
- * Returns whether the outgoing channel of the socket has already been
- * closed.
- *
- * @return {@code true} if writing to this socket is not possible anymore,
- * {@code false} otherwise.
- */
- public boolean isOutputShutdown() {
- return isOutputShutdown;
- }
- /**
- * Sets this socket's {@link SocketOptions#SO_REUSEADDR} option.
- */
- public void setReuseAddress(boolean reuse) throws SocketException {
- checkOpenAndCreate(true);
- impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(reuse));
- }
- /**
- * Returns this socket's {@link SocketOptions#SO_REUSEADDR} setting.
- */
- public boolean getReuseAddress() throws SocketException {
- checkOpenAndCreate(true);
- return (Boolean) impl.getOption(SocketOptions.SO_REUSEADDR);
- }
- /**
- * Sets this socket's {@link SocketOptions#SO_OOBINLINE} option.
- */
- public void setOOBInline(boolean oobinline) throws SocketException {
- checkOpenAndCreate(true);
- impl.setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(oobinline));
- }
- /**
- * Returns this socket's {@link SocketOptions#SO_OOBINLINE} setting.
- */
- public boolean getOOBInline() throws SocketException {
- checkOpenAndCreate(true);
- return (Boolean) impl.getOption(SocketOptions.SO_OOBINLINE);
- }
- /**
- * Sets this socket's {@link SocketOptions#IP_TOS} value for every packet sent by this socket.
- */
- public void setTrafficClass(int value) throws SocketException {
- checkOpenAndCreate(true);
- if (value < 0 || value > 255) {
- throw new IllegalArgumentException("Value doesn't fit in an unsigned byte: " + value);
- }
- impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
- }
- /**
- * Returns this socket's {@see SocketOptions#IP_TOS} setting.
- */
- public int getTrafficClass() throws SocketException {
- checkOpenAndCreate(true);
- return (Integer) impl.getOption(SocketOptions.IP_TOS);
- }
- /**
- * Sends the given single byte data which is represented by the lowest octet
- * of {@code value} as "TCP urgent data".
- *
- * @param value
- * the byte of urgent data to be sent.
- * @throws IOException
- * if an error occurs while sending urgent data.
- */
- public void sendUrgentData(int value) throws IOException {
- impl.sendUrgentData(value);
- }
- /**
- * Set the appropriate flags for a socket created by {@code
- * ServerSocket.accept()}.
- *
- * @see ServerSocket#implAccept
- */
- void accepted() {
- isCreated = isBound = isConnected = true;
- cacheLocalAddress();
- }
- private void cacheLocalAddress() {
- this.localAddress = IoBridge.getSocketLocalAddress(impl.fd);
- }
- /**
- * Returns this socket's {@code SocketChannel}, if one exists. A channel is
- * available only if this socket wraps a channel. (That is, you can go from a
- * channel to a socket and back again, but you can't go from an arbitrary socket to a channel.)
- * In practice, this means that the socket must have been created by
- * {@link java.nio.channels.ServerSocketChannel#accept} or
- * {@link java.nio.channels.SocketChannel#open}.
- */
- public SocketChannel getChannel() {
- return null;
- }
- /**
- * @hide internal use only
- */
- public FileDescriptor getFileDescriptor$() {
- return impl.fd;
- }
- /**
- * Sets performance preferences for connectionTime, latency and bandwidth.
- *
- * <p>This method does currently nothing.
- *
- * @param connectionTime
- * the value representing the importance of a short connecting
- * time.
- * @param latency
- * the value representing the importance of low latency.
- * @param bandwidth
- * the value representing the importance of high 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
- }
- }