PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/xmlvm2c/lib/proxies/java/net/Socket.java

https://github.com/tisoft/xmlvm
Java | 1146 lines | 453 code | 84 blank | 609 comment | 65 complexity | 55040edc07c375ec3a2b75d38b28ae9d MD5 | raw file
Possible License(s): LGPL-2.1
  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.IOException;
  19. import java.io.InputStream;
  20. import java.io.OutputStream;
  21. import java.nio.channels.SocketChannel;
  22. import java.security.AccessController;
  23. import org.apache.harmony.luni.net.NetUtil;
  24. import org.apache.harmony.luni.net.PlainSocketImpl;
  25. import org.apache.harmony.luni.platform.Platform;
  26. import org.apache.harmony.luni.internal.nls.Messages;
  27. import org.apache.harmony.luni.util.PriviAction;
  28. /**
  29. * Provides a client-side TCP socket.
  30. */
  31. public class Socket {
  32. SocketImpl impl;
  33. static SocketImplFactory factory;
  34. private volatile boolean isCreated = false;
  35. private boolean isBound = false;
  36. private boolean isConnected = false;
  37. private boolean isClosed = false;
  38. private boolean isInputShutdown = false;
  39. private boolean isOutputShutdown = false;
  40. private static class ConnectLock {
  41. }
  42. private Object connectLock = new ConnectLock();
  43. private Proxy proxy;
  44. static final int MULTICAST_IF = 1;
  45. static final int MULTICAST_TTL = 2;
  46. static final int TCP_NODELAY = 4;
  47. static final int FLAG_SHUTDOWN = 8;
  48. static {
  49. Platform.getNetworkSystem().oneTimeInitialization(true);
  50. }
  51. /**
  52. * Creates a new unconnected socket. When a SocketImplFactory is defined it
  53. * creates the internal socket implementation, otherwise the default socket
  54. * implementation will be used for this socket.
  55. *
  56. * @see SocketImplFactory
  57. * @see SocketImpl
  58. */
  59. public Socket() {
  60. impl = factory != null ? factory.createSocketImpl()
  61. : new PlainSocketImpl();
  62. }
  63. /**
  64. * Creates a new unconnected socket using the given proxy type. When a
  65. * {@code SocketImplFactory} is defined it creates the internal socket
  66. * implementation, otherwise the default socket implementation will be used
  67. * for this socket.
  68. * <p>
  69. * Example that will create a socket connection through a {@code SOCKS}
  70. * proxy server: <br>
  71. * {@code Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new
  72. * InetSocketAddress("test.domain.org", 2130)));}
  73. *
  74. * @param proxy
  75. * the specified proxy for this socket.
  76. * @throws IllegalArgumentException
  77. * if the argument {@code proxy} is {@code null} or of an
  78. * invalid type.
  79. * @throws SecurityException
  80. * if a security manager exists and it denies the permission to
  81. * connect to the given proxy.
  82. * @see SocketImplFactory
  83. * @see SocketImpl
  84. */
  85. public Socket(Proxy proxy) {
  86. if (null == proxy || Proxy.Type.HTTP == proxy.type()) {
  87. // luni.73=Proxy is null or invalid type
  88. throw new IllegalArgumentException(Messages.getString("luni.73")); //$NON-NLS-1$
  89. }
  90. InetSocketAddress address = (InetSocketAddress) proxy.address();
  91. if (null != address) {
  92. InetAddress addr = address.getAddress();
  93. String host;
  94. if (null != addr) {
  95. host = addr.getHostAddress();
  96. } else {
  97. host = address.getHostName();
  98. }
  99. int port = address.getPort();
  100. checkConnectPermission(host, port);
  101. }
  102. impl = factory != null ? factory.createSocketImpl()
  103. : new PlainSocketImpl(proxy);
  104. this.proxy = proxy;
  105. }
  106. /**
  107. * Creates a new streaming socket connected to the target host specified by
  108. * the parameters {@code dstName} and {@code dstPort}. The socket is bound
  109. * to any available port on the local host.
  110. *
  111. * @param dstName
  112. * the target host name or IP address to connect to.
  113. * @param dstPort
  114. * the port on the target host to connect to.
  115. * @throws UnknownHostException
  116. * if the host name could not be resolved into an IP address.
  117. * @throws IOException
  118. * if an error occurs while creating the socket.
  119. * @throws SecurityException
  120. * if a security manager exists and it denies the permission to
  121. * connect to the given address and port.
  122. */
  123. public Socket(String dstName, int dstPort) throws UnknownHostException,
  124. IOException {
  125. this();
  126. InetAddress dstAddress = InetAddress.getByName(dstName);
  127. checkDestination(dstAddress, dstPort);
  128. startupSocket(dstAddress, dstPort, null, 0, true);
  129. }
  130. /**
  131. * Creates a new streaming socket connected to the target host specified by
  132. * the parameters {@code dstName} and {@code dstPort}. On the local endpoint
  133. * the socket is bound to the given address {@code localAddress} on port
  134. * {@code localPort}.
  135. *
  136. * If {@code host} is {@code null} a loopback address is used to connect to.
  137. *
  138. * @param dstName
  139. * the target host name or IP address to connect to.
  140. * @param dstPort
  141. * the port on the target host to connect to.
  142. * @param localAddress
  143. * the address on the local host to bind to.
  144. * @param localPort
  145. * the port on the local host to bind to.
  146. * @throws UnknownHostException
  147. * if the host name could not be resolved into an IP address.
  148. * @throws IOException
  149. * if an error occurs while creating the socket.
  150. * @throws SecurityException
  151. * if a security manager exists and it denies the permission to
  152. * connect to the given address and port.
  153. */
  154. public Socket(String dstName, int dstPort, InetAddress localAddress,
  155. int localPort) throws IOException {
  156. this();
  157. InetAddress dstAddress = InetAddress.getByName(dstName);
  158. checkDestination(dstAddress, dstPort);
  159. startupSocket(dstAddress, dstPort, localAddress, localPort, true);
  160. }
  161. /**
  162. * Creates a new streaming or datagram socket connected to the target host
  163. * specified by the parameters {@code hostName} and {@code port}. The socket
  164. * is bound to any available port on the local host.
  165. *
  166. * @param hostName
  167. * the target host name or IP address to connect to.
  168. * @param port
  169. * the port on the target host to connect to.
  170. * @param streaming
  171. * if {@code true} a streaming socket is returned, a datagram
  172. * socket otherwise.
  173. * @throws UnknownHostException
  174. * if the host name could not be resolved into an IP address.
  175. * @throws IOException
  176. * if an error occurs while creating the socket.
  177. * @throws SecurityException
  178. * if a security manager exists and it denies the permission to
  179. * connect to the given address and port.
  180. * @deprecated Use {@code Socket(String, int)} instead of this for streaming
  181. * sockets or an appropriate constructor of {@code
  182. * DatagramSocket} for UDP transport.
  183. */
  184. @Deprecated
  185. public Socket(String hostName, int port, boolean streaming)
  186. throws IOException {
  187. this();
  188. InetAddress host = InetAddress.getByName(hostName);
  189. checkDestination(host, port);
  190. startupSocket(host, port, null, 0, streaming);
  191. }
  192. /**
  193. * Creates a new streaming socket connected to the target host specified by
  194. * the parameters {@code dstAddress} and {@code dstPort}. The socket is
  195. * bound to any available port on the local host.
  196. *
  197. * @param dstAddress
  198. * the target host address to connect to.
  199. * @param dstPort
  200. * the port on the target host to connect to.
  201. * @throws IOException
  202. * if an error occurs while creating the socket.
  203. * @throws SecurityException
  204. * if a security manager exists and it denies the permission to
  205. * connect to the given address and port.
  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. * @throws SecurityException
  229. * if a security manager exists and it denies the permission to
  230. * connect to the given address and port.
  231. */
  232. public Socket(InetAddress dstAddress, int dstPort,
  233. InetAddress localAddress, int localPort) throws IOException {
  234. this();
  235. checkDestination(dstAddress, dstPort);
  236. startupSocket(dstAddress, dstPort, localAddress, localPort, true);
  237. }
  238. /**
  239. * Creates a new streaming or datagram socket connected to the target host
  240. * specified by the parameters {@code addr} and {@code port}. The socket is
  241. * bound to any available port on the local host.
  242. *
  243. * @param addr
  244. * the Internet address to connect to.
  245. * @param port
  246. * the port on the target host to connect to.
  247. * @param streaming
  248. * if {@code true} a streaming socket is returned, a datagram
  249. * socket otherwise.
  250. * @throws IOException
  251. * if an error occurs while creating the socket.
  252. * @throws SecurityException
  253. * if a security manager exists and it denies the permission to
  254. * connect to the given address and port.
  255. * @deprecated Use {@code Socket(InetAddress, int)} instead of this for
  256. * streaming sockets or an appropriate constructor of {@code
  257. * DatagramSocket} for UDP transport.
  258. */
  259. @Deprecated
  260. public Socket(InetAddress addr, int port, boolean streaming)
  261. throws IOException {
  262. this();
  263. checkDestination(addr, port);
  264. startupSocket(addr, port, null, 0, streaming);
  265. }
  266. /**
  267. * Creates an unconnected socket with the given socket implementation.
  268. *
  269. * @param anImpl
  270. * the socket implementation to be used.
  271. * @throws SocketException
  272. * if an error occurs while creating the socket.
  273. */
  274. protected Socket(SocketImpl anImpl) throws SocketException {
  275. impl = anImpl;
  276. }
  277. /**
  278. * Checks whether the connection destination satisfies the security policy
  279. * and the validity of the port range.
  280. *
  281. * @param destAddr
  282. * the destination host address.
  283. * @param dstPort
  284. * the port on the destination host.
  285. */
  286. void checkDestination(InetAddress destAddr, int dstPort) {
  287. if (dstPort < 0 || dstPort > 65535) {
  288. throw new IllegalArgumentException(Messages.getString("luni.38")); //$NON-NLS-1$
  289. }
  290. checkConnectPermission(destAddr.getHostName(), dstPort);
  291. }
  292. /**
  293. * Checks whether the connection destination satisfies the security policy.
  294. *
  295. * @param hostname
  296. * the destination hostname.
  297. * @param dstPort
  298. * the port on the destination host.
  299. */
  300. private void checkConnectPermission(String hostname, int dstPort) {
  301. SecurityManager security = System.getSecurityManager();
  302. if (security != null) {
  303. security.checkConnect(hostname, dstPort);
  304. }
  305. }
  306. /**
  307. * Closes the socket. It is not possible to reconnect or rebind to this
  308. * socket thereafter which means a new socket instance has to be created.
  309. *
  310. * @throws IOException
  311. * if an error occurs while closing the socket.
  312. */
  313. public synchronized void close() throws IOException {
  314. isClosed = true;
  315. impl.close();
  316. }
  317. /**
  318. * Gets the IP address of the target host this socket is connected to.
  319. *
  320. * @return the IP address of the connected target host or {@code null} if
  321. * this socket is not yet connected.
  322. */
  323. public InetAddress getInetAddress() {
  324. if (!isConnected()) {
  325. return null;
  326. }
  327. return impl.getInetAddress();
  328. }
  329. /**
  330. * Gets an input stream to read data from this socket.
  331. *
  332. * @return the byte-oriented input stream.
  333. * @throws IOException
  334. * if an error occurs while creating the input stream or the
  335. * socket is in an invalid state.
  336. */
  337. public InputStream getInputStream() throws IOException {
  338. checkClosedAndCreate(false);
  339. if (isInputShutdown()) {
  340. throw new SocketException(Messages.getString("luni.74")); //$NON-NLS-1$
  341. }
  342. return impl.getInputStream();
  343. }
  344. /**
  345. * Gets the setting of the socket option {@code SocketOptions.SO_KEEPALIVE}.
  346. *
  347. * @return {@code true} if the {@code SocketOptions.SO_KEEPALIVE} is
  348. * enabled, {@code false} otherwise.
  349. * @throws SocketException
  350. * if an error occurs while reading the socket option.
  351. * @see SocketOptions#SO_KEEPALIVE
  352. */
  353. public boolean getKeepAlive() throws SocketException {
  354. checkClosedAndCreate(true);
  355. return ((Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE))
  356. .booleanValue();
  357. }
  358. /**
  359. * Gets the local IP address this socket is bound to.
  360. *
  361. * @return the local IP address of this socket or {@code InetAddress.ANY} if
  362. * the socket is unbound.
  363. */
  364. public InetAddress getLocalAddress() {
  365. if (!isBound()) {
  366. return InetAddress.ANY;
  367. }
  368. return Platform.getNetworkSystem().getSocketLocalAddress(impl.fd,
  369. InetAddress.preferIPv6Addresses());
  370. }
  371. /**
  372. * Gets the local port this socket is bound to.
  373. *
  374. * @return the local port of this socket or {@code -1} if the socket is
  375. * unbound.
  376. */
  377. public int getLocalPort() {
  378. if (!isBound()) {
  379. return -1;
  380. }
  381. return impl.getLocalPort();
  382. }
  383. /**
  384. * Gets an output stream to write data into this socket.
  385. *
  386. * @return the byte-oriented output stream.
  387. * @throws IOException
  388. * if an error occurs while creating the output stream or the
  389. * socket is in an invalid state.
  390. */
  391. public OutputStream getOutputStream() throws IOException {
  392. checkClosedAndCreate(false);
  393. if (isOutputShutdown()) {
  394. throw new SocketException(Messages.getString("luni.75")); //$NON-NLS-1$
  395. }
  396. return impl.getOutputStream();
  397. }
  398. /**
  399. * Gets the port number of the target host this socket is connected to.
  400. *
  401. * @return the port number of the connected target host or {@code 0} if this
  402. * socket is not yet connected.
  403. */
  404. public int getPort() {
  405. if (!isConnected()) {
  406. return 0;
  407. }
  408. return impl.getPort();
  409. }
  410. /**
  411. * Gets the value of the socket option {@code SocketOptions.SO_LINGER}.
  412. *
  413. * @return the current value of the option {@code SocketOptions.SO_LINGER}
  414. * or {@code -1} if this option is disabled.
  415. * @throws SocketException
  416. * if an error occurs while reading the socket option.
  417. * @see SocketOptions#SO_LINGER
  418. */
  419. public int getSoLinger() throws SocketException {
  420. checkClosedAndCreate(true);
  421. return ((Integer) impl.getOption(SocketOptions.SO_LINGER)).intValue();
  422. }
  423. /**
  424. * Gets the receive buffer size of this socket.
  425. *
  426. * @return the current value of the option {@code SocketOptions.SO_RCVBUF}.
  427. * @throws SocketException
  428. * if an error occurs while reading the socket option.
  429. * @see SocketOptions#SO_RCVBUF
  430. */
  431. public synchronized int getReceiveBufferSize() throws SocketException {
  432. checkClosedAndCreate(true);
  433. return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
  434. }
  435. /**
  436. * Gets the send buffer size of this socket.
  437. *
  438. * @return the current value of the option {@code SocketOptions.SO_SNDBUF}.
  439. * @throws SocketException
  440. * if an error occurs while reading the socket option.
  441. * @see SocketOptions#SO_SNDBUF
  442. */
  443. public synchronized int getSendBufferSize() throws SocketException {
  444. checkClosedAndCreate(true);
  445. return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
  446. }
  447. /**
  448. * Gets the timeout for this socket during which a reading operation shall
  449. * block while waiting for data.
  450. *
  451. * @return the current value of the option {@code SocketOptions.SO_TIMEOUT}
  452. * or {@code 0} which represents an infinite timeout.
  453. * @throws SocketException
  454. * if an error occurs while reading the socket option.
  455. * @see SocketOptions#SO_TIMEOUT
  456. */
  457. public synchronized int getSoTimeout() throws SocketException {
  458. checkClosedAndCreate(true);
  459. return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
  460. }
  461. /**
  462. * Gets the setting of the socket option {@code SocketOptions.TCP_NODELAY}.
  463. *
  464. * @return {@code true} if the {@code SocketOptions.TCP_NODELAY} is enabled,
  465. * {@code false} otherwise.
  466. * @throws SocketException
  467. * if an error occurs while reading the socket option.
  468. * @see SocketOptions#TCP_NODELAY
  469. */
  470. public boolean getTcpNoDelay() throws SocketException {
  471. checkClosedAndCreate(true);
  472. return ((Boolean) impl.getOption(SocketOptions.TCP_NODELAY))
  473. .booleanValue();
  474. }
  475. /**
  476. * Sets the state of the {@code SocketOptions.SO_KEEPALIVE} for this socket.
  477. *
  478. * @param value
  479. * the state whether this option is enabled or not.
  480. * @throws SocketException
  481. * if an error occurs while setting the option.
  482. * @see SocketOptions#SO_KEEPALIVE
  483. */
  484. public void setKeepAlive(boolean value) throws SocketException {
  485. if (impl != null) {
  486. checkClosedAndCreate(true);
  487. impl.setOption(SocketOptions.SO_KEEPALIVE, value ? Boolean.TRUE
  488. : Boolean.FALSE);
  489. }
  490. }
  491. /**
  492. * Sets the internal factory for creating socket implementations. This may
  493. * only be executed once during the lifetime of the application.
  494. *
  495. * @param fac
  496. * the socket implementation factory to be set.
  497. * @throws IOException
  498. * if the factory has been already set.
  499. */
  500. public static synchronized void setSocketImplFactory(SocketImplFactory fac)
  501. throws IOException {
  502. SecurityManager security = System.getSecurityManager();
  503. if (security != null) {
  504. security.checkSetFactory();
  505. }
  506. if (factory != null) {
  507. throw new SocketException(Messages.getString("luni.5C")); //$NON-NLS-1$
  508. }
  509. factory = fac;
  510. }
  511. /**
  512. * Sets the send buffer size of this socket.
  513. *
  514. * @param size
  515. * the buffer size in bytes. This value must be a positive number
  516. * greater than {@code 0}.
  517. * @throws SocketException
  518. * if an error occurs while setting the size or the given value
  519. * is an invalid size.
  520. * @see SocketOptions#SO_SNDBUF
  521. */
  522. public synchronized void setSendBufferSize(int size) throws SocketException {
  523. checkClosedAndCreate(true);
  524. if (size < 1) {
  525. throw new IllegalArgumentException(Messages.getString("luni.5A")); //$NON-NLS-1$
  526. }
  527. impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
  528. }
  529. /**
  530. * Sets the receive buffer size of this socket.
  531. *
  532. * @param size
  533. * the buffer size in bytes. This value must be a positive number
  534. * greater than {@code 0}.
  535. * @throws SocketException
  536. * if an error occurs while setting the size or the given value
  537. * is an invalid size.
  538. * @see SocketOptions#SO_RCVBUF
  539. */
  540. public synchronized void setReceiveBufferSize(int size)
  541. throws SocketException {
  542. checkClosedAndCreate(true);
  543. if (size < 1) {
  544. throw new IllegalArgumentException(Messages.getString("luni.5A")); //$NON-NLS-1$
  545. }
  546. impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
  547. }
  548. /**
  549. * Sets the state of the {@code SocketOptions.SO_LINGER} with the given
  550. * timeout in seconds. The timeout value for this option is silently limited
  551. * to the maximum of {@code 65535}.
  552. *
  553. * @param on
  554. * the state whether this option is enabled or not.
  555. * @param timeout
  556. * the linger timeout value in seconds.
  557. * @throws SocketException
  558. * if an error occurs while setting the option.
  559. * @see SocketOptions#SO_LINGER
  560. */
  561. public void setSoLinger(boolean on, int timeout) throws SocketException {
  562. checkClosedAndCreate(true);
  563. if (on && timeout < 0) {
  564. throw new IllegalArgumentException(Messages.getString("luni.76")); //$NON-NLS-1$
  565. }
  566. int val = on ? (65535 < timeout ? 65535 : timeout) : -1;
  567. impl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(val));
  568. }
  569. /**
  570. * Sets the reading timeout in milliseconds for this socket. The read
  571. * operation will block indefinitely if this option value is set to {@code
  572. * 0}. The timeout must be set before calling the read operation. A
  573. * {@code SocketTimeoutException} is thrown when this timeout expires.
  574. *
  575. * @param timeout
  576. * the reading timeout value as number greater than {@code 0} or
  577. * {@code 0} for an infinite timeout.
  578. * @throws SocketException
  579. * if an error occurs while setting the option.
  580. * @see SocketOptions#SO_TIMEOUT
  581. */
  582. public synchronized void setSoTimeout(int timeout) throws SocketException {
  583. checkClosedAndCreate(true);
  584. if (timeout < 0) {
  585. throw new IllegalArgumentException(Messages.getString("luni.5B")); //$NON-NLS-1$
  586. }
  587. impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
  588. }
  589. /**
  590. * Sets the state of the {@code SocketOptions.TCP_NODELAY} for this socket.
  591. *
  592. * @param on
  593. * the state whether this option is enabled or not.
  594. * @throws SocketException
  595. * if an error occurs while setting the option.
  596. * @see SocketOptions#TCP_NODELAY
  597. */
  598. public void setTcpNoDelay(boolean on) throws SocketException {
  599. checkClosedAndCreate(true);
  600. impl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
  601. }
  602. /**
  603. * Creates a stream socket, binds it to the nominated local address/port,
  604. * then connects it to the nominated destination address/port.
  605. *
  606. * @param dstAddress
  607. * the destination host address.
  608. * @param dstPort
  609. * the port on the destination host.
  610. * @param localAddress
  611. * the address on the local machine to bind.
  612. * @param localPort
  613. * the port on the local machine to bind.
  614. * @throws IOException
  615. * thrown if an error occurs during the bind or connect
  616. * operations.
  617. */
  618. void startupSocket(InetAddress dstAddress, int dstPort,
  619. InetAddress localAddress, int localPort, boolean streaming)
  620. throws IOException {
  621. if (localPort < 0 || localPort > 65535) {
  622. throw new IllegalArgumentException(Messages.getString("luni.77")); //$NON-NLS-1$
  623. }
  624. InetAddress addr = localAddress == null ? InetAddress.ANY
  625. : localAddress;
  626. synchronized (this) {
  627. impl.create(streaming);
  628. isCreated = true;
  629. try {
  630. if (!streaming || !NetUtil.usingSocks(proxy)) {
  631. impl.bind(addr, localPort);
  632. }
  633. isBound = true;
  634. impl.connect(dstAddress, dstPort);
  635. isConnected = true;
  636. } catch (IOException e) {
  637. impl.close();
  638. throw e;
  639. }
  640. }
  641. }
  642. /**
  643. * Returns a {@code String} containing a concise, human-readable description of the
  644. * socket.
  645. *
  646. * @return the textual representation of this socket.
  647. */
  648. @Override
  649. public String toString() {
  650. if (!isConnected()) {
  651. return "Socket[unconnected]"; //$NON-NLS-1$
  652. }
  653. return impl.toString();
  654. }
  655. /**
  656. * Closes the input stream of this socket. Any further data sent to this
  657. * socket will be discarded. Reading from this socket after this method has
  658. * been called will return the value {@code EOF}.
  659. *
  660. * @throws IOException
  661. * if an error occurs while closing the socket input stream.
  662. * @throws SocketException
  663. * if the input stream is already closed.
  664. */
  665. public void shutdownInput() throws IOException {
  666. if (isInputShutdown()) {
  667. throw new SocketException(Messages.getString("luni.74")); //$NON-NLS-1$
  668. }
  669. checkClosedAndCreate(false);
  670. impl.shutdownInput();
  671. isInputShutdown = true;
  672. }
  673. /**
  674. * Closes the output stream of this socket. All buffered data will be sent
  675. * followed by the termination sequence. Writing to the closed output stream
  676. * will cause an {@code IOException}.
  677. *
  678. * @throws IOException
  679. * if an error occurs while closing the socket output stream.
  680. * @throws SocketException
  681. * if the output stream is already closed.
  682. */
  683. public void shutdownOutput() throws IOException {
  684. if (isOutputShutdown()) {
  685. throw new SocketException(Messages.getString("luni.75")); //$NON-NLS-1$
  686. }
  687. checkClosedAndCreate(false);
  688. impl.shutdownOutput();
  689. isOutputShutdown = true;
  690. }
  691. /**
  692. * Checks whether the socket is closed, and throws an exception. Otherwise
  693. * creates the underlying SocketImpl.
  694. *
  695. * @throws SocketException
  696. * if the socket is closed.
  697. */
  698. private void checkClosedAndCreate(boolean create) throws SocketException {
  699. if (isClosed()) {
  700. throw new SocketException(Messages.getString("luni.0C")); //$NON-NLS-1$
  701. }
  702. if (!create) {
  703. if (!isConnected()) {
  704. throw new SocketException(Messages.getString("luni.78")); //$NON-NLS-1$
  705. // a connected socket must be created
  706. }
  707. /*
  708. * return directly to fix a possible bug, if !create, should return
  709. * here
  710. */
  711. return;
  712. }
  713. if (isCreated) {
  714. return;
  715. }
  716. synchronized (this) {
  717. if (isCreated) {
  718. return;
  719. }
  720. try {
  721. impl.create(true);
  722. } catch (SocketException e) {
  723. throw e;
  724. } catch (IOException e) {
  725. throw new SocketException(e.toString());
  726. }
  727. isCreated = true;
  728. }
  729. }
  730. /**
  731. * Gets the local address and port of this socket as a SocketAddress or
  732. * {@code null} if the socket is unbound. This is useful on multihomed
  733. * hosts.
  734. *
  735. * @return the bound local socket address and port.
  736. */
  737. public SocketAddress getLocalSocketAddress() {
  738. if (!isBound()) {
  739. return null;
  740. }
  741. return new InetSocketAddress(getLocalAddress(), getLocalPort());
  742. }
  743. /**
  744. * Gets the remote address and port of this socket as a {@code
  745. * SocketAddress} or {@code null} if the socket is not connected.
  746. *
  747. * @return the remote socket address and port.
  748. */
  749. public SocketAddress getRemoteSocketAddress() {
  750. if (!isConnected()) {
  751. return null;
  752. }
  753. return new InetSocketAddress(getInetAddress(), getPort());
  754. }
  755. /**
  756. * Returns whether this socket is bound to a local address and port.
  757. *
  758. * @return {@code true} if the socket is bound to a local address, {@code
  759. * false} otherwise.
  760. */
  761. public boolean isBound() {
  762. return isBound;
  763. }
  764. /**
  765. * Returns whether this socket is connected to a remote host.
  766. *
  767. * @return {@code true} if the socket is connected, {@code false} otherwise.
  768. */
  769. public boolean isConnected() {
  770. return isConnected;
  771. }
  772. /**
  773. * Returns whether this socket is closed.
  774. *
  775. * @return {@code true} if the socket is closed, {@code false} otherwise.
  776. */
  777. public boolean isClosed() {
  778. return isClosed;
  779. }
  780. /**
  781. * Binds this socket to the given local host address and port specified by
  782. * the SocketAddress {@code localAddr}. If {@code localAddr} is set to
  783. * {@code null}, this socket will be bound to an available local address on
  784. * any free port.
  785. *
  786. * @param localAddr
  787. * the specific address and port on the local machine to bind to.
  788. * @throws IllegalArgumentException
  789. * if the given SocketAddress is invalid or not supported.
  790. * @throws IOException
  791. * if the socket is already bound or an error occurs while
  792. * binding.
  793. */
  794. public void bind(SocketAddress localAddr) throws IOException {
  795. checkClosedAndCreate(true);
  796. if (isBound()) {
  797. throw new BindException(Messages.getString("luni.71")); //$NON-NLS-1$
  798. }
  799. int port = 0;
  800. InetAddress addr = InetAddress.ANY;
  801. if (localAddr != null) {
  802. if (!(localAddr instanceof InetSocketAddress)) {
  803. throw new IllegalArgumentException(Messages.getString(
  804. "luni.49", localAddr.getClass())); //$NON-NLS-1$
  805. }
  806. InetSocketAddress inetAddr = (InetSocketAddress) localAddr;
  807. if ((addr = inetAddr.getAddress()) == null) {
  808. throw new SocketException(Messages.getString(
  809. "luni.1A", inetAddr.getHostName())); //$NON-NLS-1$
  810. }
  811. port = inetAddr.getPort();
  812. }
  813. synchronized (this) {
  814. try {
  815. impl.bind(addr, port);
  816. isBound = true;
  817. } catch (IOException e) {
  818. impl.close();
  819. throw e;
  820. }
  821. }
  822. }
  823. /**
  824. * Connects this socket to the given remote host address and port specified
  825. * by the SocketAddress {@code remoteAddr}.
  826. *
  827. * @param remoteAddr
  828. * the address and port of the remote host to connect to.
  829. * @throws IllegalArgumentException
  830. * if the given SocketAddress is invalid or not supported.
  831. * @throws IOException
  832. * if the socket is already connected or an error occurs while
  833. * connecting.
  834. */
  835. public void connect(SocketAddress remoteAddr) throws IOException {
  836. connect(remoteAddr, 0);
  837. }
  838. /**
  839. * Connects this socket to the given remote host address and port specified
  840. * by the SocketAddress {@code remoteAddr} with the specified timeout. The
  841. * connecting method will block until the connection is established or an
  842. * error occurred.
  843. *
  844. * @param remoteAddr
  845. * the address and port of the remote host to connect to.
  846. * @param timeout
  847. * the timeout value in milliseconds or {@code 0} for an infinite
  848. * timeout.
  849. * @throws IllegalArgumentException
  850. * if the given SocketAddress is invalid or not supported or the
  851. * timeout value is negative.
  852. * @throws IOException
  853. * if the socket is already connected or an error occurs while
  854. * connecting.
  855. */
  856. public void connect(SocketAddress remoteAddr, int timeout)
  857. throws IOException {
  858. checkClosedAndCreate(true);
  859. if (timeout < 0) {
  860. throw new IllegalArgumentException(Messages.getString("luni.5B")); //$NON-NLS-1$
  861. }
  862. if (isConnected()) {
  863. throw new SocketException(Messages.getString("luni.5F")); //$NON-NLS-1$
  864. }
  865. if (remoteAddr == null) {
  866. throw new IllegalArgumentException(Messages.getString("luni.5D")); //$NON-NLS-1$
  867. }
  868. if (!(remoteAddr instanceof InetSocketAddress)) {
  869. throw new IllegalArgumentException(Messages.getString(
  870. "luni.49", remoteAddr.getClass())); //$NON-NLS-1$
  871. }
  872. InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr;
  873. InetAddress addr;
  874. if ((addr = inetAddr.getAddress()) == null) {
  875. throw new UnknownHostException(Messages.getString("luni.1A", remoteAddr));//$NON-NLS-1$
  876. }
  877. int port = inetAddr.getPort();
  878. checkDestination(addr, port);
  879. synchronized (connectLock) {
  880. try {
  881. if (!isBound()) {
  882. // socket allready created at this point by earlier call or
  883. // checkClosedAndCreate this caused us to lose socket
  884. // options on create
  885. // impl.create(true);
  886. if (!NetUtil.usingSocks(proxy)) {
  887. impl.bind(InetAddress.ANY, 0);
  888. }
  889. isBound = true;
  890. }
  891. impl.connect(remoteAddr, timeout);
  892. isConnected = true;
  893. } catch (IOException e) {
  894. impl.close();
  895. throw e;
  896. }
  897. }
  898. }
  899. /**
  900. * Returns whether the incoming channel of the socket has already been
  901. * closed.
  902. *
  903. * @return {@code true} if reading from this socket is not possible anymore,
  904. * {@code false} otherwise.
  905. */
  906. public boolean isInputShutdown() {
  907. return isInputShutdown;
  908. }
  909. /**
  910. * Returns whether the outgoing channel of the socket has already been
  911. * closed.
  912. *
  913. * @return {@code true} if writing to this socket is not possible anymore,
  914. * {@code false} otherwise.
  915. */
  916. public boolean isOutputShutdown() {
  917. return isOutputShutdown;
  918. }
  919. /**
  920. * Sets the state of the {@code SocketOptions.SO_REUSEADDR} for this socket.
  921. *
  922. * @param reuse
  923. * the state whether this option is enabled or not.
  924. * @throws SocketException
  925. * if an error occurs while setting the option.
  926. * @see SocketOptions#SO_REUSEADDR
  927. */
  928. public void setReuseAddress(boolean reuse) throws SocketException {
  929. checkClosedAndCreate(true);
  930. impl.setOption(SocketOptions.SO_REUSEADDR, reuse ? Boolean.TRUE
  931. : Boolean.FALSE);
  932. }
  933. /**
  934. * Gets the setting of the socket option {@code SocketOptions.SO_REUSEADDR}.
  935. *
  936. * @return {@code true} if the {@code SocketOptions.SO_REUSEADDR} is
  937. * enabled, {@code false} otherwise.
  938. * @throws SocketException
  939. * if an error occurs while reading the socket option.
  940. * @see SocketOptions#SO_REUSEADDR
  941. */
  942. public boolean getReuseAddress() throws SocketException {
  943. checkClosedAndCreate(true);
  944. return ((Boolean) impl.getOption(SocketOptions.SO_REUSEADDR))
  945. .booleanValue();
  946. }
  947. /**
  948. * Sets the state of the {@code SocketOptions.SO_OOBINLINE} for this socket.
  949. * When this option is enabled urgent data can be received in-line with
  950. * normal data.
  951. *
  952. * @param oobinline
  953. * whether this option is enabled or not.
  954. * @throws SocketException
  955. * if an error occurs while setting the option.
  956. * @see SocketOptions#SO_OOBINLINE
  957. */
  958. public void setOOBInline(boolean oobinline) throws SocketException {
  959. checkClosedAndCreate(true);
  960. impl.setOption(SocketOptions.SO_OOBINLINE, oobinline ? Boolean.TRUE
  961. : Boolean.FALSE);
  962. }
  963. /**
  964. * Gets the setting of the socket option {@code SocketOptions.SO_OOBINLINE}.
  965. *
  966. * @return {@code true} if the {@code SocketOptions.SO_OOBINLINE} is
  967. * enabled, {@code false} otherwise.
  968. * @throws SocketException
  969. * if an error occurs while reading the socket option.
  970. * @see SocketOptions#SO_OOBINLINE
  971. */
  972. public boolean getOOBInline() throws SocketException {
  973. checkClosedAndCreate(true);
  974. return ((Boolean) impl.getOption(SocketOptions.SO_OOBINLINE))
  975. .booleanValue();
  976. }
  977. /**
  978. * Sets the value of the {@code SocketOptions.IP_TOS} for this socket. See
  979. * the specification RFC 1349 for more information about the type of service
  980. * field.
  981. *
  982. * @param value
  983. * the value to be set for this option with a valid range of
  984. * {@code 0-255}.
  985. * @throws SocketException
  986. * if an error occurs while setting the option.
  987. * @see SocketOptions#IP_TOS
  988. */
  989. public void setTrafficClass(int value) throws SocketException {
  990. checkClosedAndCreate(true);
  991. if (value < 0 || value > 255) {
  992. throw new IllegalArgumentException();
  993. }
  994. impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
  995. }
  996. /**
  997. * Gets the value of the socket option {@code SocketOptions.IP_TOS}.
  998. *
  999. * @return the value which represents the type of service.
  1000. * @throws SocketException
  1001. * if an error occurs while reading the socket option.
  1002. * @see SocketOptions#IP_TOS
  1003. */
  1004. public int getTrafficClass() throws SocketException {
  1005. checkClosedAndCreate(true);
  1006. return ((Number) impl.getOption(SocketOptions.IP_TOS)).intValue();
  1007. }
  1008. /**
  1009. * Sends the given single byte data which is represented by the lowest octet
  1010. * of {@code value} as "TCP urgent data".
  1011. *
  1012. * @param value
  1013. * the byte of urgent data to be sent.
  1014. * @throws IOException
  1015. * if an error occurs while sending urgent data.
  1016. */
  1017. public void sendUrgentData(int value) throws IOException {
  1018. if (!impl.supportsUrgentData()) {
  1019. throw new SocketException(Messages.getString("luni.79")); //$NON-NLS-1$
  1020. }
  1021. impl.sendUrgentData(value);
  1022. }
  1023. /**
  1024. * Set the appropriate flags for a socket created by {@code
  1025. * ServerSocket.accept()}.
  1026. *
  1027. * @see ServerSocket#implAccept
  1028. */
  1029. void accepted() {
  1030. isCreated = isBound = isConnected = true;
  1031. }
  1032. static boolean preferIPv4Stack() {
  1033. return NetUtil.preferIPv4Stack();
  1034. }
  1035. /**
  1036. * Gets the SocketChannel of this socket, if one is available. The current
  1037. * implementation of this method returns always {@code null}.
  1038. *
  1039. * @return the related SocketChannel or {@code null} if no channel exists.
  1040. */
  1041. public SocketChannel getChannel() {
  1042. return null;
  1043. }
  1044. /**
  1045. * Sets performance preferences for connectionTime, latency and bandwidth.
  1046. * <p>
  1047. * This method does currently nothing.
  1048. *
  1049. * @param connectionTime
  1050. * the value representing the importance of a short connecting
  1051. * time.
  1052. * @param latency
  1053. * the value representing the importance of low latency.
  1054. * @param bandwidth
  1055. * the value representing the importance of high bandwidth.
  1056. */
  1057. public void setPerformancePreferences(int connectionTime, int latency,
  1058. int bandwidth) {
  1059. // Our socket implementation only provide one protocol: TCP/IP, so
  1060. // we do nothing for this method
  1061. }
  1062. }