PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

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

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