PageRenderTime 49ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/luni/src/main/java/java/net/Socket.java

https://bitbucket.org/jpilliet/libcore-292
Java | 990 lines | 425 code | 74 blank | 491 comment | 62 complexity | 4580724db40b7b6c425d625d1677eade MD5 | raw file
Possible License(s): JSON, BSD-3-Clause
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package java.net;
  18. import java.io.Closeable;
  19. import java.io.FileDescriptor;
  20. import java.io.IOException;
  21. import java.io.InputStream;
  22. import java.io.OutputStream;
  23. import java.nio.channels.SocketChannel;
  24. import libcore.io.IoBridge;
  25. /**
  26. * Provides a client-side TCP socket.
  27. */
  28. public class Socket implements Closeable {
  29. private static SocketImplFactory factory;
  30. final SocketImpl impl;
  31. private final Proxy proxy;
  32. volatile boolean isCreated = false;
  33. private boolean isBound = false;
  34. private boolean isConnected = false;
  35. private boolean isClosed = false;
  36. private boolean isInputShutdown = false;
  37. private boolean isOutputShutdown = false;
  38. private InetAddress localAddress = Inet4Address.ANY;
  39. private final Object connectLock = new Object();
  40. /**
  41. * Creates a new unconnected socket. When a SocketImplFactory is defined it
  42. * creates the internal socket implementation, otherwise the default socket
  43. * implementation will be used for this socket.
  44. *
  45. * @see SocketImplFactory
  46. * @see SocketImpl
  47. */
  48. public Socket() {
  49. this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl();
  50. this.proxy = null;
  51. }
  52. /**
  53. * Creates a new unconnected socket using the given proxy type. When a
  54. * {@code SocketImplFactory} is defined it creates the internal socket
  55. * implementation, otherwise the default socket implementation will be used
  56. * for this socket.
  57. * <p>
  58. * Example that will create a socket connection through a {@code SOCKS}
  59. * proxy server: <br>
  60. * {@code Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new
  61. * InetSocketAddress("test.domain.org", 2130)));}
  62. *
  63. * @param proxy
  64. * the specified proxy for this socket.
  65. * @throws IllegalArgumentException
  66. * if the argument {@code proxy} is {@code null} or of an
  67. * invalid type.
  68. * @see SocketImplFactory
  69. * @see SocketImpl
  70. */
  71. public Socket(Proxy proxy) {
  72. if (proxy == null || proxy.type() == Proxy.Type.HTTP) {
  73. throw new IllegalArgumentException("Invalid proxy: " + proxy);
  74. }
  75. this.proxy = proxy;
  76. this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl(proxy);
  77. }
  78. /**
  79. * Tries to connect a socket to all IP addresses of the given hostname.
  80. *
  81. * @param dstName
  82. * the target host name or IP address to connect to.
  83. * @param dstPort
  84. * the port on the target host to connect to.
  85. * @param localAddress
  86. * the address on the local host to bind to.
  87. * @param localPort
  88. * the port on the local host to bind to.
  89. * @param streaming
  90. * if {@code true} a streaming socket is returned, a datagram
  91. * socket otherwise.
  92. * @throws UnknownHostException
  93. * if the host name could not be resolved into an IP address.
  94. * @throws IOException
  95. * if an error occurs while creating the socket.
  96. */
  97. private void tryAllAddresses(String dstName, int dstPort, InetAddress
  98. localAddress, int localPort, boolean streaming) throws IOException {
  99. InetAddress[] dstAddresses = InetAddress.getAllByName(dstName);
  100. // Loop through all the destination addresses except the last, trying to
  101. // connect to each one and ignoring errors. There must be at least one
  102. // address, or getAllByName would have thrown UnknownHostException.
  103. InetAddress dstAddress;
  104. for (int i = 0; i < dstAddresses.length - 1; i++) {
  105. dstAddress = dstAddresses[i];
  106. try {
  107. checkDestination(dstAddress, dstPort);
  108. startupSocket(dstAddress, dstPort, localAddress, localPort, streaming);
  109. return;
  110. } catch (IOException ex) {
  111. }
  112. }
  113. // Now try to connect to the last address in the array, handing back to
  114. // the caller any exceptions that are thrown.
  115. dstAddress = dstAddresses[dstAddresses.length - 1];
  116. checkDestination(dstAddress, dstPort);
  117. startupSocket(dstAddress, dstPort, localAddress, localPort, streaming);
  118. }
  119. /**
  120. * Creates a new streaming socket connected to the target host specified by
  121. * the parameters {@code dstName} and {@code dstPort}. The socket is bound
  122. * to any available port on the local host.
  123. *
  124. * <p>This implementation tries each IP address for the given hostname (in
  125. * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
  126. * until it either connects successfully or it exhausts the set.
  127. *
  128. * @param dstName
  129. * the target host name or IP address to connect to.
  130. * @param dstPort
  131. * the port on the target host to connect to.
  132. * @throws UnknownHostException
  133. * if the host name could not be resolved into an IP address.
  134. * @throws IOException
  135. * if an error occurs while creating the socket.
  136. */
  137. public Socket(String dstName, int dstPort) throws UnknownHostException, IOException {
  138. this(dstName, dstPort, null, 0);
  139. }
  140. /**
  141. * Creates a new streaming socket connected to the target host specified by
  142. * the parameters {@code dstName} and {@code dstPort}. On the local endpoint
  143. * the socket is bound to the given address {@code localAddress} on port
  144. * {@code localPort}. If {@code host} is {@code null} a loopback address is used to connect to.
  145. *
  146. * <p>This implementation tries each IP address for the given hostname (in
  147. * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
  148. * until it either connects successfully or it exhausts the set.
  149. *
  150. * @param dstName
  151. * the target host name or IP address to connect to.
  152. * @param dstPort
  153. * the port on the target host to connect to.
  154. * @param localAddress
  155. * the address on the local host to bind to.
  156. * @param localPort
  157. * the port on the local host to bind to.
  158. * @throws UnknownHostException
  159. * if the host name could not be resolved into an IP address.
  160. * @throws IOException
  161. * if an error occurs while creating the socket.
  162. */
  163. public Socket(String dstName, int dstPort, InetAddress localAddress, int localPort) throws IOException {
  164. this();
  165. tryAllAddresses(dstName, dstPort, localAddress, localPort, true);
  166. }
  167. /**
  168. * Creates a new streaming or datagram socket connected to the target host
  169. * specified by the parameters {@code hostName} and {@code port}. The socket
  170. * is bound to any available port on the local host.
  171. *
  172. * <p>This implementation tries each IP address for the given hostname (in
  173. * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
  174. * until it either connects successfully or it exhausts the set.
  175. *
  176. * @param hostName
  177. * the target host name or IP address to connect to.
  178. * @param port
  179. * the port on the target host to connect to.
  180. * @param streaming
  181. * if {@code true} a streaming socket is returned, a datagram
  182. * socket otherwise.
  183. * @throws UnknownHostException
  184. * if the host name could not be resolved into an IP address.
  185. * @throws IOException
  186. * if an error occurs while creating the socket.
  187. * @deprecated Use {@code Socket(String, int)} instead of this for streaming
  188. * sockets or an appropriate constructor of {@code
  189. * DatagramSocket} for UDP transport.
  190. */
  191. @Deprecated
  192. public Socket(String hostName, int port, boolean streaming) throws IOException {
  193. this();
  194. tryAllAddresses(hostName, port, null, 0, streaming);
  195. }
  196. /**
  197. * Creates a new streaming socket connected to the target host specified by
  198. * the parameters {@code dstAddress} and {@code dstPort}. The socket is
  199. * bound to any available port on the local host.
  200. *
  201. * @param dstAddress
  202. * the target host address to connect to.
  203. * @param dstPort
  204. * the port on the target host to connect to.
  205. * @throws IOException
  206. * if an error occurs while creating the socket.
  207. */
  208. public Socket(InetAddress dstAddress, int dstPort) throws IOException {
  209. this();
  210. checkDestination(dstAddress, dstPort);
  211. startupSocket(dstAddress, dstPort, null, 0, true);
  212. }
  213. /**
  214. * Creates a new streaming socket connected to the target host specified by
  215. * the parameters {@code dstAddress} and {@code dstPort}. On the local
  216. * endpoint the socket is bound to the given address {@code localAddress} on
  217. * port {@code localPort}.
  218. *
  219. * @param dstAddress
  220. * the target host address to connect to.
  221. * @param dstPort
  222. * the port on the target host to connect to.
  223. * @param localAddress
  224. * the address on the local host to bind to.
  225. * @param localPort
  226. * the port on the local host to bind to.
  227. * @throws IOException
  228. * if an error occurs while creating the socket.
  229. */
  230. public Socket(InetAddress dstAddress, int dstPort,
  231. InetAddress localAddress, int localPort) throws IOException {
  232. this();
  233. checkDestination(dstAddress, dstPort);
  234. startupSocket(dstAddress, dstPort, localAddress, localPort, true);
  235. }
  236. /**
  237. * Creates a new streaming or datagram socket connected to the target host
  238. * specified by the parameters {@code addr} and {@code port}. The socket is
  239. * bound to any available port on the local host.
  240. *
  241. * @param addr
  242. * the Internet address to connect to.
  243. * @param port
  244. * the port on the target host to connect to.
  245. * @param streaming
  246. * if {@code true} a streaming socket is returned, a datagram
  247. * socket otherwise.
  248. * @throws IOException
  249. * if an error occurs while creating the socket.
  250. * @deprecated Use {@code Socket(InetAddress, int)} instead of this for
  251. * streaming sockets or an appropriate constructor of {@code
  252. * DatagramSocket} for UDP transport.
  253. */
  254. @Deprecated
  255. public Socket(InetAddress addr, int port, boolean streaming) throws IOException {
  256. this();
  257. checkDestination(addr, port);
  258. startupSocket(addr, port, null, 0, streaming);
  259. }
  260. /**
  261. * Creates an unconnected socket with the given socket implementation.
  262. *
  263. * @param impl
  264. * the socket implementation to be used.
  265. * @throws SocketException
  266. * if an error occurs while creating the socket.
  267. */
  268. protected Socket(SocketImpl impl) throws SocketException {
  269. this.impl = impl;
  270. this.proxy = null;
  271. }
  272. /**
  273. * Checks whether the connection destination satisfies the security policy
  274. * and the validity of the port range.
  275. *
  276. * @param destAddr
  277. * the destination host address.
  278. * @param dstPort
  279. * the port on the destination host.
  280. */
  281. private void checkDestination(InetAddress destAddr, int dstPort) {
  282. if (dstPort < 0 || dstPort > 65535) {
  283. throw new IllegalArgumentException("Port out of range: " + dstPort);
  284. }
  285. }
  286. /**
  287. * Closes the socket. It is not possible to reconnect or rebind to this
  288. * socket thereafter which means a new socket instance has to be created.
  289. *
  290. * @throws IOException
  291. * if an error occurs while closing the socket.
  292. */
  293. public synchronized void close() throws IOException {
  294. isClosed = true;
  295. // RI compatibility: the RI returns the any address (but the original local port) after close.
  296. localAddress = Inet4Address.ANY;
  297. impl.close();
  298. }
  299. /**
  300. * Returns the IP address of the target host this socket is connected to, or null if this
  301. * socket is not yet connected.
  302. */
  303. public InetAddress getInetAddress() {
  304. if (!isConnected()) {
  305. return null;
  306. }
  307. return impl.getInetAddress();
  308. }
  309. /**
  310. * Returns an input stream to read data from this socket.
  311. *
  312. * @return the byte-oriented input stream.
  313. * @throws IOException
  314. * if an error occurs while creating the input stream or the
  315. * socket is in an invalid state.
  316. */
  317. public InputStream getInputStream() throws IOException {
  318. checkOpenAndCreate(false);
  319. if (isInputShutdown()) {
  320. throw new SocketException("Socket input is shutdown");
  321. }
  322. return impl.getInputStream();
  323. }
  324. /**
  325. * Returns this socket's {@link SocketOptions#SO_KEEPALIVE} setting.
  326. */
  327. public boolean getKeepAlive() throws SocketException {
  328. checkOpenAndCreate(true);
  329. return (Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE);
  330. }
  331. /**
  332. * Returns the local IP address this socket is bound to, or {@code InetAddress.ANY} if
  333. * the socket is unbound.
  334. */
  335. public InetAddress getLocalAddress() {
  336. return localAddress;
  337. }
  338. /**
  339. * Returns the local port this socket is bound to, or -1 if the socket is unbound.
  340. */
  341. public int getLocalPort() {
  342. if (!isBound()) {
  343. return -1;
  344. }
  345. return impl.getLocalPort();
  346. }
  347. /**
  348. * Returns an output stream to write data into this socket.
  349. *
  350. * @return the byte-oriented output stream.
  351. * @throws IOException
  352. * if an error occurs while creating the output stream or the
  353. * socket is in an invalid state.
  354. */
  355. public OutputStream getOutputStream() throws IOException {
  356. checkOpenAndCreate(false);
  357. if (isOutputShutdown()) {
  358. throw new SocketException("Socket output is shutdown");
  359. }
  360. return impl.getOutputStream();
  361. }
  362. /**
  363. * Returns the port number of the target host this socket is connected to, or 0 if this socket
  364. * is not yet connected.
  365. */
  366. public int getPort() {
  367. if (!isConnected()) {
  368. return 0;
  369. }
  370. return impl.getPort();
  371. }
  372. /**
  373. * Returns this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds, or -1
  374. * for no linger (i.e. {@code close} will return immediately).
  375. */
  376. public int getSoLinger() throws SocketException {
  377. checkOpenAndCreate(true);
  378. // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
  379. Object value = impl.getOption(SocketOptions.SO_LINGER);
  380. if (value instanceof Integer) {
  381. return (Integer) value;
  382. } else {
  383. return -1;
  384. }
  385. }
  386. /**
  387. * Returns this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
  388. */
  389. public synchronized int getReceiveBufferSize() throws SocketException {
  390. checkOpenAndCreate(true);
  391. return (Integer) impl.getOption(SocketOptions.SO_RCVBUF);
  392. }
  393. /**
  394. * Returns this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
  395. */
  396. public synchronized int getSendBufferSize() throws SocketException {
  397. checkOpenAndCreate(true);
  398. return (Integer) impl.getOption(SocketOptions.SO_SNDBUF);
  399. }
  400. /**
  401. * Returns this socket's {@link SocketOptions#SO_TIMEOUT receive timeout}.
  402. */
  403. public synchronized int getSoTimeout() throws SocketException {
  404. checkOpenAndCreate(true);
  405. return (Integer) impl.getOption(SocketOptions.SO_TIMEOUT);
  406. }
  407. /**
  408. * Returns this socket's {@code SocketOptions#TCP_NODELAY} setting.
  409. */
  410. public boolean getTcpNoDelay() throws SocketException {
  411. checkOpenAndCreate(true);
  412. return (Boolean) impl.getOption(SocketOptions.TCP_NODELAY);
  413. }
  414. /**
  415. * Sets this socket's {@link SocketOptions#SO_KEEPALIVE} option.
  416. */
  417. public void setKeepAlive(boolean keepAlive) throws SocketException {
  418. if (impl != null) {
  419. checkOpenAndCreate(true);
  420. impl.setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(keepAlive));
  421. }
  422. }
  423. /**
  424. * Sets the internal factory for creating socket implementations. This may
  425. * only be executed once during the lifetime of the application.
  426. *
  427. * @param fac
  428. * the socket implementation factory to be set.
  429. * @throws IOException
  430. * if the factory has been already set.
  431. */
  432. public static synchronized void setSocketImplFactory(SocketImplFactory fac)
  433. throws IOException {
  434. if (factory != null) {
  435. throw new SocketException("Factory already set");
  436. }
  437. factory = fac;
  438. }
  439. /**
  440. * Sets this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
  441. */
  442. public synchronized void setSendBufferSize(int size) throws SocketException {
  443. checkOpenAndCreate(true);
  444. if (size < 1) {
  445. throw new IllegalArgumentException("size < 1");
  446. }
  447. impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
  448. }
  449. /**
  450. * Sets this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
  451. */
  452. public synchronized void setReceiveBufferSize(int size) throws SocketException {
  453. checkOpenAndCreate(true);
  454. if (size < 1) {
  455. throw new IllegalArgumentException("size < 1");
  456. }
  457. impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
  458. }
  459. /**
  460. * Sets this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds.
  461. * If {@code on} is false, {@code timeout} is irrelevant.
  462. */
  463. public void setSoLinger(boolean on, int timeout) throws SocketException {
  464. checkOpenAndCreate(true);
  465. // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
  466. if (on && timeout < 0) {
  467. throw new IllegalArgumentException("timeout < 0");
  468. }
  469. if (on) {
  470. impl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(timeout));
  471. } else {
  472. impl.setOption(SocketOptions.SO_LINGER, Boolean.FALSE);
  473. }
  474. }
  475. /**
  476. * Sets this socket's {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds.
  477. * Use 0 for no timeout.
  478. * To take effect, this option must be set before the blocking method was called.
  479. */
  480. public synchronized void setSoTimeout(int timeout) throws SocketException {
  481. checkOpenAndCreate(true);
  482. if (timeout < 0) {
  483. throw new IllegalArgumentException("timeout < 0");
  484. }
  485. impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
  486. }
  487. /**
  488. * Sets this socket's {@link SocketOptions#TCP_NODELAY} option.
  489. */
  490. public void setTcpNoDelay(boolean on) throws SocketException {
  491. checkOpenAndCreate(true);
  492. impl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
  493. }
  494. /**
  495. * Creates a stream socket, binds it to the nominated local address/port,
  496. * then connects it to the nominated destination address/port.
  497. *
  498. * @param dstAddress
  499. * the destination host address.
  500. * @param dstPort
  501. * the port on the destination host.
  502. * @param localAddress
  503. * the address on the local machine to bind.
  504. * @param localPort
  505. * the port on the local machine to bind.
  506. * @throws IOException
  507. * thrown if an error occurs during the bind or connect
  508. * operations.
  509. */
  510. private void startupSocket(InetAddress dstAddress, int dstPort,
  511. InetAddress localAddress, int localPort, boolean streaming)
  512. throws IOException {
  513. if (localPort < 0 || localPort > 65535) {
  514. throw new IllegalArgumentException("Local port out of range: " + localPort);
  515. }
  516. InetAddress addr = localAddress == null ? Inet4Address.ANY : localAddress;
  517. synchronized (this) {
  518. impl.create(streaming);
  519. isCreated = true;
  520. try {
  521. if (!streaming || !usingSocks()) {
  522. impl.bind(addr, localPort);
  523. }
  524. isBound = true;
  525. impl.connect(dstAddress, dstPort);
  526. isConnected = true;
  527. cacheLocalAddress();
  528. } catch (IOException e) {
  529. impl.close();
  530. throw e;
  531. }
  532. }
  533. }
  534. private boolean usingSocks() {
  535. return proxy != null && proxy.type() == Proxy.Type.SOCKS;
  536. }
  537. /**
  538. * Returns a {@code String} containing a concise, human-readable description of the
  539. * socket.
  540. *
  541. * @return the textual representation of this socket.
  542. */
  543. @Override
  544. public String toString() {
  545. if (!isConnected()) {
  546. return "Socket[unconnected]";
  547. }
  548. return impl.toString();
  549. }
  550. /**
  551. * Closes the input stream of this socket. Any further data sent to this
  552. * socket will be discarded. Reading from this socket after this method has
  553. * been called will return the value {@code EOF}.
  554. *
  555. * @throws IOException
  556. * if an error occurs while closing the socket input stream.
  557. * @throws SocketException
  558. * if the input stream is already closed.
  559. */
  560. public void shutdownInput() throws IOException {
  561. if (isInputShutdown()) {
  562. throw new SocketException("Socket input is shutdown");
  563. }
  564. checkOpenAndCreate(false);
  565. impl.shutdownInput();
  566. isInputShutdown = true;
  567. }
  568. /**
  569. * Closes the output stream of this socket. All buffered data will be sent
  570. * followed by the termination sequence. Writing to the closed output stream
  571. * will cause an {@code IOException}.
  572. *
  573. * @throws IOException
  574. * if an error occurs while closing the socket output stream.
  575. * @throws SocketException
  576. * if the output stream is already closed.
  577. */
  578. public void shutdownOutput() throws IOException {
  579. if (isOutputShutdown()) {
  580. throw new SocketException("Socket output is shutdown");
  581. }
  582. checkOpenAndCreate(false);
  583. impl.shutdownOutput();
  584. isOutputShutdown = true;
  585. }
  586. /**
  587. * Checks whether the socket is closed, and throws an exception. Otherwise
  588. * creates the underlying SocketImpl.
  589. *
  590. * @throws SocketException
  591. * if the socket is closed.
  592. */
  593. private void checkOpenAndCreate(boolean create) throws SocketException {
  594. if (isClosed()) {
  595. throw new SocketException("Socket is closed");
  596. }
  597. if (!create) {
  598. if (!isConnected()) {
  599. throw new SocketException("Socket is not connected");
  600. // a connected socket must be created
  601. }
  602. /*
  603. * return directly to fix a possible bug, if !create, should return
  604. * here
  605. */
  606. return;
  607. }
  608. if (isCreated) {
  609. return;
  610. }
  611. synchronized (this) {
  612. if (isCreated) {
  613. return;
  614. }
  615. try {
  616. impl.create(true);
  617. } catch (SocketException e) {
  618. throw e;
  619. } catch (IOException e) {
  620. throw new SocketException(e.toString());
  621. }
  622. isCreated = true;
  623. }
  624. }
  625. /**
  626. * Returns the local address and port of this socket as a SocketAddress or
  627. * null if the socket is unbound. This is useful on multihomed
  628. * hosts.
  629. */
  630. public SocketAddress getLocalSocketAddress() {
  631. if (!isBound()) {
  632. return null;
  633. }
  634. return new InetSocketAddress(getLocalAddress(), getLocalPort());
  635. }
  636. /**
  637. * Returns the remote address and port of this socket as a {@code
  638. * SocketAddress} or null if the socket is not connected.
  639. *
  640. * @return the remote socket address and port.
  641. */
  642. public SocketAddress getRemoteSocketAddress() {
  643. if (!isConnected()) {
  644. return null;
  645. }
  646. return new InetSocketAddress(getInetAddress(), getPort());
  647. }
  648. /**
  649. * Returns whether this socket is bound to a local address and port.
  650. *
  651. * @return {@code true} if the socket is bound to a local address, {@code
  652. * false} otherwise.
  653. */
  654. public boolean isBound() {
  655. return isBound;
  656. }
  657. /**
  658. * Returns whether this socket is connected to a remote host.
  659. *
  660. * @return {@code true} if the socket is connected, {@code false} otherwise.
  661. */
  662. public boolean isConnected() {
  663. return isConnected;
  664. }
  665. /**
  666. * Returns whether this socket is closed.
  667. *
  668. * @return {@code true} if the socket is closed, {@code false} otherwise.
  669. */
  670. public boolean isClosed() {
  671. return isClosed;
  672. }
  673. /**
  674. * Binds this socket to the given local host address and port specified by
  675. * the SocketAddress {@code localAddr}. If {@code localAddr} is set to
  676. * {@code null}, this socket will be bound to an available local address on
  677. * any free port.
  678. *
  679. * @param localAddr
  680. * the specific address and port on the local machine to bind to.
  681. * @throws IllegalArgumentException
  682. * if the given SocketAddress is invalid or not supported.
  683. * @throws IOException
  684. * if the socket is already bound or an error occurs while
  685. * binding.
  686. */
  687. public void bind(SocketAddress localAddr) throws IOException {
  688. checkOpenAndCreate(true);
  689. if (isBound()) {
  690. throw new BindException("Socket is already bound");
  691. }
  692. int port = 0;
  693. InetAddress addr = Inet4Address.ANY;
  694. if (localAddr != null) {
  695. if (!(localAddr instanceof InetSocketAddress)) {
  696. throw new IllegalArgumentException("Local address not an InetSocketAddress: " +
  697. localAddr.getClass());
  698. }
  699. InetSocketAddress inetAddr = (InetSocketAddress) localAddr;
  700. if ((addr = inetAddr.getAddress()) == null) {
  701. throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName());
  702. }
  703. port = inetAddr.getPort();
  704. }
  705. synchronized (this) {
  706. try {
  707. impl.bind(addr, port);
  708. isBound = true;
  709. cacheLocalAddress();
  710. } catch (IOException e) {
  711. impl.close();
  712. throw e;
  713. }
  714. }
  715. }
  716. /**
  717. * Connects this socket to the given remote host address and port specified
  718. * by the SocketAddress {@code remoteAddr}.
  719. *
  720. * @param remoteAddr
  721. * the address and port of the remote host to connect to.
  722. * @throws IllegalArgumentException
  723. * if the given SocketAddress is invalid or not supported.
  724. * @throws IOException
  725. * if the socket is already connected or an error occurs while
  726. * connecting.
  727. */
  728. public void connect(SocketAddress remoteAddr) throws IOException {
  729. connect(remoteAddr, 0);
  730. }
  731. /**
  732. * Connects this socket to the given remote host address and port specified
  733. * by the SocketAddress {@code remoteAddr} with the specified timeout. The
  734. * connecting method will block until the connection is established or an
  735. * error occurred.
  736. *
  737. * @param remoteAddr
  738. * the address and port of the remote host to connect to.
  739. * @param timeout
  740. * the timeout value in milliseconds or {@code 0} for an infinite
  741. * timeout.
  742. * @throws IllegalArgumentException
  743. * if the given SocketAddress is invalid or not supported or the
  744. * timeout value is negative.
  745. * @throws IOException
  746. * if the socket is already connected or an error occurs while
  747. * connecting.
  748. */
  749. public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
  750. checkOpenAndCreate(true);
  751. if (timeout < 0) {
  752. throw new IllegalArgumentException("timeout < 0");
  753. }
  754. if (isConnected()) {
  755. throw new SocketException("Already connected");
  756. }
  757. if (remoteAddr == null) {
  758. throw new IllegalArgumentException("remoteAddr == null");
  759. }
  760. if (!(remoteAddr instanceof InetSocketAddress)) {
  761. throw new IllegalArgumentException("Remote address not an InetSocketAddress: " +
  762. remoteAddr.getClass());
  763. }
  764. InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr;
  765. InetAddress addr;
  766. if ((addr = inetAddr.getAddress()) == null) {
  767. throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName());
  768. }
  769. int port = inetAddr.getPort();
  770. checkDestination(addr, port);
  771. synchronized (connectLock) {
  772. try {
  773. if (!isBound()) {
  774. // socket already created at this point by earlier call or
  775. // checkOpenAndCreate this caused us to lose socket
  776. // options on create
  777. // impl.create(true);
  778. if (!usingSocks()) {
  779. impl.bind(Inet4Address.ANY, 0);
  780. }
  781. isBound = true;
  782. }
  783. impl.connect(remoteAddr, timeout);
  784. isConnected = true;
  785. cacheLocalAddress();
  786. } catch (IOException e) {
  787. impl.close();
  788. throw e;
  789. }
  790. }
  791. }
  792. /**
  793. * Returns whether the incoming channel of the socket has already been
  794. * closed.
  795. *
  796. * @return {@code true} if reading from this socket is not possible anymore,
  797. * {@code false} otherwise.
  798. */
  799. public boolean isInputShutdown() {
  800. return isInputShutdown;
  801. }
  802. /**
  803. * Returns whether the outgoing channel of the socket has already been
  804. * closed.
  805. *
  806. * @return {@code true} if writing to this socket is not possible anymore,
  807. * {@code false} otherwise.
  808. */
  809. public boolean isOutputShutdown() {
  810. return isOutputShutdown;
  811. }
  812. /**
  813. * Sets this socket's {@link SocketOptions#SO_REUSEADDR} option.
  814. */
  815. public void setReuseAddress(boolean reuse) throws SocketException {
  816. checkOpenAndCreate(true);
  817. impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(reuse));
  818. }
  819. /**
  820. * Returns this socket's {@link SocketOptions#SO_REUSEADDR} setting.
  821. */
  822. public boolean getReuseAddress() throws SocketException {
  823. checkOpenAndCreate(true);
  824. return (Boolean) impl.getOption(SocketOptions.SO_REUSEADDR);
  825. }
  826. /**
  827. * Sets this socket's {@link SocketOptions#SO_OOBINLINE} option.
  828. */
  829. public void setOOBInline(boolean oobinline) throws SocketException {
  830. checkOpenAndCreate(true);
  831. impl.setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(oobinline));
  832. }
  833. /**
  834. * Returns this socket's {@link SocketOptions#SO_OOBINLINE} setting.
  835. */
  836. public boolean getOOBInline() throws SocketException {
  837. checkOpenAndCreate(true);
  838. return (Boolean) impl.getOption(SocketOptions.SO_OOBINLINE);
  839. }
  840. /**
  841. * Sets this socket's {@link SocketOptions#IP_TOS} value for every packet sent by this socket.
  842. */
  843. public void setTrafficClass(int value) throws SocketException {
  844. checkOpenAndCreate(true);
  845. if (value < 0 || value > 255) {
  846. throw new IllegalArgumentException("Value doesn't fit in an unsigned byte: " + value);
  847. }
  848. impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
  849. }
  850. /**
  851. * Returns this socket's {@see SocketOptions#IP_TOS} setting.
  852. */
  853. public int getTrafficClass() throws SocketException {
  854. checkOpenAndCreate(true);
  855. return (Integer) impl.getOption(SocketOptions.IP_TOS);
  856. }
  857. /**
  858. * Sends the given single byte data which is represented by the lowest octet
  859. * of {@code value} as "TCP urgent data".
  860. *
  861. * @param value
  862. * the byte of urgent data to be sent.
  863. * @throws IOException
  864. * if an error occurs while sending urgent data.
  865. */
  866. public void sendUrgentData(int value) throws IOException {
  867. impl.sendUrgentData(value);
  868. }
  869. /**
  870. * Set the appropriate flags for a socket created by {@code
  871. * ServerSocket.accept()}.
  872. *
  873. * @see ServerSocket#implAccept
  874. */
  875. void accepted() throws SocketException {
  876. isCreated = isBound = isConnected = true;
  877. cacheLocalAddress();
  878. }
  879. private void cacheLocalAddress() throws SocketException {
  880. this.localAddress = IoBridge.getSocketLocalAddress(impl.fd);
  881. }
  882. /**
  883. * Returns this socket's {@code SocketChannel}, if one exists. A channel is
  884. * available only if this socket wraps a channel. (That is, you can go from a
  885. * channel to a socket and back again, but you can't go from an arbitrary socket to a channel.)
  886. * In practice, this means that the socket must have been created by
  887. * {@link java.nio.channels.ServerSocketChannel#accept} or
  888. * {@link java.nio.channels.SocketChannel#open}.
  889. */
  890. public SocketChannel getChannel() {
  891. return null;
  892. }
  893. /**
  894. * @hide internal use only
  895. */
  896. public FileDescriptor getFileDescriptor$() {
  897. return impl.fd;
  898. }
  899. /**
  900. * Sets performance preferences for connectionTime, latency and bandwidth.
  901. *
  902. * <p>This method does currently nothing.
  903. *
  904. * @param connectionTime
  905. * the value representing the importance of a short connecting
  906. * time.
  907. * @param latency
  908. * the value representing the importance of low latency.
  909. * @param bandwidth
  910. * the value representing the importance of high bandwidth.
  911. */
  912. public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
  913. // Our socket implementation only provide one protocol: TCP/IP, so
  914. // we do nothing for this method
  915. }
  916. }