PageRenderTime 60ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/org.pouzinsociety.org.jnode.net.support/src/main/java/jnode/net/Socket.java

https://github.com/PouzinSociety/tinos
Java | 1276 lines | 482 code | 130 blank | 664 comment | 77 complexity | 067d29be4084c85528fa09172b392c2d MD5 | raw file
  1. /* Socket.java -- Client socket implementation
  2. Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004
  3. Free Software Foundation, Inc.
  4. This file is part of GNU Classpath.
  5. GNU Classpath is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. GNU Classpath is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Classpath; see the file COPYING. If not, write to the
  15. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. 02110-1301 USA.
  17. Linking this library statically or dynamically with other modules is
  18. making a combined work based on this library. Thus, the terms and
  19. conditions of the GNU General Public License cover the whole
  20. combination.
  21. As a special exception, the copyright holders of this library give you
  22. permission to link this library with independent modules to produce an
  23. executable, regardless of the license terms of these independent
  24. modules, and to copy and distribute the resulting executable under
  25. terms of your choice, provided that you also meet, for each linked
  26. independent module, the terms and conditions of the license of that
  27. module. An independent module is a module which is not derived from
  28. or based on this library. If you modify this library, you may extend
  29. this exception to your version of the library, but you are not
  30. obligated to do so. If you do not wish to do so, delete this
  31. exception statement from your version. */
  32. /*
  33. * 2008 - 2010 (c) Waterford Institute of Technology
  34. * TSSG, EU ICT 4WARD
  35. *
  36. * 2010 (c) Pouzin Society
  37. * - Forked from EU ICT 4WARD Open Source Distribution.
  38. * - Organisation Strings updated to reflect fork.
  39. *
  40. *
  41. * Author : pphelan(at)tssg.org
  42. *
  43. * Modifications : Changes to port JNode code base to OSGi platform.
  44. * - java.net -> jnode.net
  45. */
  46. package jnode.net;
  47. //import gnu.java.net.PlainSocketImpl;
  48. import java.io.IOException;
  49. import java.io.InputStream;
  50. import java.io.OutputStream;
  51. import java.net.SocketException;
  52. import java.net.SocketOptions;
  53. import java.net.UnknownHostException;
  54. import java.nio.channels.IllegalBlockingModeException;
  55. import java.nio.channels.SocketChannel;
  56. /* Written using on-line Java Platform 1.2 API Specification.
  57. * Status: I believe all methods are implemented.
  58. */
  59. /**
  60. * This class models a client site socket. A socket is a TCP/IP endpoint
  61. * for network communications conceptually similar to a file handle.
  62. * <p>
  63. * This class does not actually do any work. Instead, it redirects all of
  64. * its calls to a socket implementation object which implements the
  65. * <code>SocketImpl</code> interface. The implementation class is
  66. * instantiated by factory class that implements the
  67. * <code>SocketImplFactory interface</code>. A default
  68. * factory is provided, however the factory may be set by a call to
  69. * the <code>setSocketImplFactory</code> method. Note that this may only be
  70. * done once per virtual machine. If a subsequent attempt is made to set the
  71. * factory, a <code>SocketException</code> will be thrown.
  72. *
  73. * @author Aaron M. Renn (arenn@urbanophile.com)
  74. * @author Per Bothner (bothner@cygnus.com)
  75. */
  76. public class Socket
  77. {
  78. /**
  79. * This is the user SocketImplFactory for this class. If this variable is
  80. * null, a default factory is used.
  81. */
  82. static SocketImplFactory factory;
  83. /**
  84. * The implementation object to which calls are redirected
  85. */
  86. // package-private because ServerSocket.implAccept() needs to access it.
  87. SocketImpl impl;
  88. /**
  89. * True if socket implementation was created by calling their
  90. * create() method.
  91. */
  92. // package-private because ServerSocket.implAccept() needs to access it.
  93. boolean implCreated;
  94. /**
  95. * True if the socket is bound.
  96. * Package private so it can be set from ServerSocket when accept is called.
  97. */
  98. boolean bound;
  99. /**
  100. * True if input is shutdown.
  101. */
  102. private boolean inputShutdown;
  103. /**
  104. * True if output is shutdown.
  105. */
  106. private boolean outputShutdown;
  107. /**
  108. * Initializes a new instance of <code>Socket</code> object without
  109. * connecting to a remote host. This useful for subclasses of socket that
  110. * might want this behavior.
  111. *
  112. * @specnote This constructor is public since JDK 1.4
  113. * @since 1.1
  114. */
  115. public Socket() throws SocketException
  116. {
  117. if (factory != null)
  118. impl = factory.createSocketImpl();
  119. else
  120. throw new SocketException("SocketImplFactory must be set");
  121. }
  122. /**
  123. * Initializes a new instance of <code>Socket</code> object without
  124. * connecting to a remote host. This is useful for subclasses of socket
  125. * that might want this behavior.
  126. * <p>
  127. * Additionally, this socket will be created using the supplied
  128. * implementation class instead the default class or one returned by a
  129. * factory. If this value is <code>null</code>, the default Socket
  130. * implementation is used.
  131. *
  132. * @param impl The <code>SocketImpl</code> to use for this
  133. * <code>Socket</code>
  134. *
  135. * @exception SocketException If an error occurs
  136. *
  137. * @since 1.1
  138. */
  139. protected Socket(SocketImpl impl) throws SocketException
  140. {
  141. this.impl = impl;
  142. }
  143. /**
  144. * Initializes a new instance of <code>Socket</code> and connects to the
  145. * hostname and port specified as arguments.
  146. *
  147. * @param host The name of the host to connect to
  148. * @param port The port number to connect to
  149. *
  150. * @exception UnknownHostException If the hostname cannot be resolved to a
  151. * network address.
  152. * @exception IOException If an error occurs
  153. * @exception SecurityException If a security manager exists and its
  154. * checkConnect method doesn't allow the operation
  155. */
  156. public Socket(String host, int port)
  157. throws UnknownHostException, IOException
  158. {
  159. this(InetAddress.getByName(host), port, null, 0, true);
  160. }
  161. /**
  162. * Initializes a new instance of <code>Socket</code> and connects to the
  163. * address and port number specified as arguments.
  164. *
  165. * @param address The address to connect to
  166. * @param port The port number to connect to
  167. *
  168. * @exception IOException If an error occurs
  169. * @exception SecurityException If a security manager exists and its
  170. * checkConnect method doesn't allow the operation
  171. */
  172. public Socket(InetAddress address, int port) throws IOException
  173. {
  174. this(address, port, null, 0, true);
  175. }
  176. /**
  177. * Initializes a new instance of <code>Socket</code> that connects to the
  178. * named host on the specified port and binds to the specified local address
  179. * and port.
  180. *
  181. * @param host The name of the remote host to connect to.
  182. * @param port The remote port to connect to.
  183. * @param localAddr The local address to bind to.
  184. * @param localPort The local port to bind to.
  185. *
  186. * @exception SecurityException If the <code>SecurityManager</code>
  187. * exists and does not allow a connection to the specified host/port or
  188. * binding to the specified local host/port.
  189. * @exception IOException If a connection error occurs.
  190. *
  191. * @since 1.1
  192. */
  193. public Socket(String host, int port, InetAddress localAddr, int localPort)
  194. throws IOException
  195. {
  196. this(InetAddress.getByName(host), port, localAddr, localPort, true);
  197. }
  198. /**
  199. * Initializes a new instance of <code>Socket</code> and connects to the
  200. * address and port number specified as arguments, plus binds to the
  201. * specified local address and port.
  202. *
  203. * @param address The remote address to connect to
  204. * @param port The remote port to connect to
  205. * @param localAddr The local address to connect to
  206. * @param localPort The local port to connect to
  207. *
  208. * @exception IOException If an error occurs
  209. * @exception SecurityException If a security manager exists and its
  210. * checkConnect method doesn't allow the operation
  211. *
  212. * @since 1.1
  213. */
  214. public Socket(InetAddress address, int port, InetAddress localAddr,
  215. int localPort) throws IOException
  216. {
  217. this(address, port, localAddr, localPort, true);
  218. }
  219. /**
  220. * Initializes a new instance of <code>Socket</code> and connects to the
  221. * hostname and port specified as arguments. If the stream argument is set
  222. * to <code>true</code>, then a stream socket is created. If it is
  223. * <code>false</code>, a datagram socket is created.
  224. *
  225. * @param host The name of the host to connect to
  226. * @param port The port to connect to
  227. * @param stream <code>true</code> for a stream socket, <code>false</code>
  228. * for a datagram socket
  229. *
  230. * @exception IOException If an error occurs
  231. * @exception SecurityException If a security manager exists and its
  232. * checkConnect method doesn't allow the operation
  233. *
  234. * @deprecated Use the <code>DatagramSocket</code> class to create
  235. * datagram oriented sockets.
  236. */
  237. public Socket(String host, int port, boolean stream)
  238. throws IOException
  239. {
  240. this(InetAddress.getByName(host), port, null, 0, stream);
  241. }
  242. /**
  243. * Initializes a new instance of <code>Socket</code> and connects to the
  244. * address and port number specified as arguments. If the stream param is
  245. * <code>true</code>, a stream socket will be created, otherwise a datagram
  246. * socket is created.
  247. *
  248. * @param host The address to connect to
  249. * @param port The port number to connect to
  250. * @param stream <code>true</code> to create a stream socket,
  251. * <code>false</code> to create a datagram socket.
  252. *
  253. * @exception IOException If an error occurs
  254. * @exception SecurityException If a security manager exists and its
  255. * checkConnect method doesn't allow the operation
  256. *
  257. * @deprecated Use the <code>DatagramSocket</code> class to create
  258. * datagram oriented sockets.
  259. */
  260. public Socket(InetAddress host, int port, boolean stream)
  261. throws IOException
  262. {
  263. this(host, port, null, 0, stream);
  264. }
  265. /**
  266. * This constructor is where the real work takes place. Connect to the
  267. * specified address and port. Use default local values if not specified,
  268. * otherwise use the local host and port passed in. Create as stream or
  269. * datagram based on "stream" argument.
  270. * <p>
  271. *
  272. * @param raddr The remote address to connect to
  273. * @param rport The remote port to connect to
  274. * @param laddr The local address to connect to
  275. * @param lport The local port to connect to
  276. * @param stream true for a stream socket, false for a datagram socket
  277. *
  278. * @exception IOException If an error occurs
  279. * @exception SecurityException If a security manager exists and its
  280. * checkConnect method doesn't allow the operation
  281. */
  282. private Socket(InetAddress raddr, int rport, InetAddress laddr, int lport,
  283. boolean stream) throws IOException
  284. {
  285. this();
  286. SecurityManager sm = System.getSecurityManager();
  287. if (sm != null)
  288. sm.checkConnect(raddr.getHostName(), rport);
  289. // bind socket
  290. SocketAddress bindaddr =
  291. laddr == null ? null : new InetSocketAddress(laddr, lport);
  292. bind(bindaddr);
  293. // connect socket
  294. connect(new InetSocketAddress(raddr, rport));
  295. // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
  296. // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
  297. // that default. JDK 1.2 doc infers not to do a bind.
  298. }
  299. private SocketImpl getImpl() throws SocketException
  300. {
  301. try
  302. {
  303. if (! implCreated)
  304. {
  305. impl.create(true);
  306. implCreated = true;
  307. }
  308. }
  309. catch (IOException e)
  310. {
  311. SocketException se = new SocketException(e.toString());
  312. se.initCause(e);
  313. throw se;
  314. }
  315. return impl;
  316. }
  317. /**
  318. * Binds the socket to the givent local address/port
  319. *
  320. * @param bindpoint The address/port to bind to
  321. *
  322. * @exception IOException If an error occurs
  323. * @exception SecurityException If a security manager exists and its
  324. * checkConnect method doesn't allow the operation
  325. * @exception IllegalArgumentException If the address type is not supported
  326. *
  327. * @since 1.4
  328. */
  329. public void bind(SocketAddress bindpoint) throws IOException
  330. {
  331. if (isClosed())
  332. throw new SocketException("socket is closed");
  333. // XXX: JDK 1.4.1 API documentation says that if bindpoint is null the
  334. // socket will be bound to an ephemeral port and a valid local address.
  335. if (bindpoint == null)
  336. bindpoint = new InetSocketAddress(InetAddress.ANY_IF, 0);
  337. if (! (bindpoint instanceof InetSocketAddress))
  338. throw new IllegalArgumentException();
  339. InetSocketAddress tmp = (InetSocketAddress) bindpoint;
  340. // bind to address/port
  341. try
  342. {
  343. getImpl().bind(tmp.getAddress(), tmp.getPort());
  344. bound = true;
  345. }
  346. catch (IOException exception)
  347. {
  348. exception.printStackTrace();
  349. close();
  350. throw exception;
  351. }
  352. catch (RuntimeException exception)
  353. {
  354. exception.printStackTrace();
  355. close();
  356. throw exception;
  357. }
  358. catch (Error error)
  359. {
  360. error.printStackTrace();
  361. close();
  362. throw error;
  363. }
  364. }
  365. /**
  366. * Connects the socket with a remote address.
  367. *
  368. * @param endpoint The address to connect to
  369. *
  370. * @exception IOException If an error occurs
  371. * @exception IllegalArgumentException If the addess type is not supported
  372. * @exception IllegalBlockingModeException If this socket has an associated
  373. * channel, and the channel is in non-blocking mode
  374. *
  375. * @since 1.4
  376. */
  377. public void connect(SocketAddress endpoint) throws IOException
  378. {
  379. connect(endpoint, 0);
  380. }
  381. /**
  382. * Connects the socket with a remote address. A timeout of zero is
  383. * interpreted as an infinite timeout. The connection will then block
  384. * until established or an error occurs.
  385. *
  386. * @param endpoint The address to connect to
  387. * @param timeout The length of the timeout in milliseconds, or
  388. * 0 to indicate no timeout.
  389. *
  390. * @exception IOException If an error occurs
  391. * @exception IllegalArgumentException If the address type is not supported
  392. * @exception IllegalBlockingModeException If this socket has an associated
  393. * channel, and the channel is in non-blocking mode
  394. * @exception SocketTimeoutException If the timeout is reached
  395. *
  396. * @since 1.4
  397. */
  398. public void connect(SocketAddress endpoint, int timeout)
  399. throws IOException
  400. {
  401. if (isClosed())
  402. throw new SocketException("socket is closed");
  403. if (! (endpoint instanceof InetSocketAddress))
  404. throw new IllegalArgumentException("unsupported address type");
  405. /**
  406. * TODO: Revisit Me
  407. *
  408. // The Sun spec says that if we have an associated channel and
  409. // it is in non-blocking mode, we throw an IllegalBlockingModeException.
  410. // However, in our implementation if the channel itself initiated this
  411. // operation, then we must honor it regardless of its blocking mode.
  412. if (getChannel() != null && ! getChannel().isBlocking()
  413. && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
  414. throw new IllegalBlockingModeException();
  415. */
  416. if (! isBound())
  417. bind(null);
  418. getImpl().connect(endpoint, timeout);
  419. }
  420. /**
  421. * Returns the address of the remote end of the socket. If this socket
  422. * is not connected, then <code>null</code> is returned.
  423. *
  424. * @return The remote address this socket is connected to
  425. */
  426. public InetAddress getInetAddress()
  427. {
  428. if (! isConnected())
  429. return null;
  430. try
  431. {
  432. return getImpl().getInetAddress();
  433. }
  434. catch (SocketException e)
  435. {
  436. // This cannot happen as we are connected.
  437. }
  438. return null;
  439. }
  440. /**
  441. * Returns the local address to which this socket is bound. If this socket
  442. * is not connected, then a wildcard address, for which
  443. * @see InetAddress#isAnyLocalAddress() is <code>true</code>, is returned.
  444. *
  445. * @return The local address
  446. *
  447. * @since 1.1
  448. */
  449. public InetAddress getLocalAddress()
  450. {
  451. if (! isBound())
  452. return InetAddress.ANY_IF;
  453. InetAddress addr = null;
  454. try
  455. {
  456. addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
  457. }
  458. catch (SocketException e)
  459. {
  460. // (hopefully) shouldn't happen
  461. // throw new java.lang.InternalError
  462. // ("Error in PlainSocketImpl.getOption");
  463. return null;
  464. }
  465. return addr;
  466. }
  467. /**
  468. * Returns the port number of the remote end of the socket connection. If
  469. * this socket is not connected, then 0 is returned.
  470. *
  471. * @return The remote port this socket is connected to
  472. */
  473. public int getPort()
  474. {
  475. if (! isConnected())
  476. return 0;
  477. try
  478. {
  479. return getImpl().getPort();
  480. }
  481. catch (SocketException e)
  482. {
  483. // This cannot happen as we are connected.
  484. }
  485. return 0;
  486. }
  487. /**
  488. * Returns the local port number to which this socket is bound. If this
  489. * socket is not connected, then -1 is returned.
  490. *
  491. * @return The local port
  492. */
  493. public int getLocalPort()
  494. {
  495. if (! isBound())
  496. return -1;
  497. try
  498. {
  499. if (getImpl() != null)
  500. return getImpl().getLocalPort();
  501. }
  502. catch (SocketException e)
  503. {
  504. // This cannot happen as we are bound.
  505. }
  506. return -1;
  507. }
  508. /**
  509. * Returns local socket address.
  510. *
  511. * @return the local socket address, null if not bound
  512. *
  513. * @since 1.4
  514. */
  515. public SocketAddress getLocalSocketAddress()
  516. {
  517. if (! isBound())
  518. return null;
  519. InetAddress addr = getLocalAddress();
  520. try
  521. {
  522. return new InetSocketAddress(addr, getImpl().getLocalPort());
  523. }
  524. catch (SocketException e)
  525. {
  526. // This cannot happen as we are bound.
  527. return null;
  528. }
  529. }
  530. /**
  531. * Returns the remote socket address.
  532. *
  533. * @return the remote socket address, null of not connected
  534. *
  535. * @since 1.4
  536. */
  537. public SocketAddress getRemoteSocketAddress()
  538. {
  539. if (! isConnected())
  540. return null;
  541. try
  542. {
  543. return new InetSocketAddress(getImpl().getInetAddress(),
  544. getImpl().getPort());
  545. }
  546. catch (SocketException e)
  547. {
  548. // This cannot happen as we are connected.
  549. return null;
  550. }
  551. }
  552. /**
  553. * Returns an InputStream for reading from this socket.
  554. *
  555. * @return The InputStream object
  556. *
  557. * @exception IOException If an error occurs or Socket is not connected
  558. */
  559. public InputStream getInputStream() throws IOException
  560. {
  561. if (isClosed())
  562. throw new SocketException("socket is closed");
  563. if (! isConnected())
  564. throw new IOException("not connected");
  565. return getImpl().getInputStream();
  566. }
  567. /**
  568. * Returns an OutputStream for writing to this socket.
  569. *
  570. * @return The OutputStream object
  571. *
  572. * @exception IOException If an error occurs or Socket is not connected
  573. */
  574. public OutputStream getOutputStream() throws IOException
  575. {
  576. if (isClosed())
  577. throw new SocketException("socket is closed");
  578. if (! isConnected())
  579. throw new IOException("not connected");
  580. return getImpl().getOutputStream();
  581. }
  582. /**
  583. * Sets the TCP_NODELAY option on the socket.
  584. *
  585. * @param on true to enable, false to disable
  586. *
  587. * @exception SocketException If an error occurs or Socket is not connected
  588. *
  589. * @since 1.1
  590. */
  591. public void setTcpNoDelay(boolean on) throws SocketException
  592. {
  593. if (isClosed())
  594. throw new SocketException("socket is closed");
  595. getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
  596. }
  597. /**
  598. * Tests whether or not the TCP_NODELAY option is set on the socket.
  599. * Returns true if enabled, false if disabled. When on it disables the
  600. * Nagle algorithm which means that packets are always send immediatly and
  601. * never merged together to reduce network trafic.
  602. *
  603. * @return Whether or not TCP_NODELAY is set
  604. *
  605. * @exception SocketException If an error occurs or Socket not connected
  606. *
  607. * @since 1.1
  608. */
  609. public boolean getTcpNoDelay() throws SocketException
  610. {
  611. if (isClosed())
  612. throw new SocketException("socket is closed");
  613. Object on = getImpl().getOption(SocketOptions.TCP_NODELAY);
  614. if (on instanceof Boolean)
  615. return (((Boolean) on).booleanValue());
  616. else
  617. throw new SocketException("Internal Error");
  618. }
  619. /**
  620. * Sets the value of the SO_LINGER option on the socket. If the
  621. * SO_LINGER option is set on a socket and there is still data waiting to
  622. * be sent when the socket is closed, then the close operation will block
  623. * until either that data is delivered or until the timeout period
  624. * expires. The linger interval is specified in hundreths of a second
  625. * (platform specific?)
  626. *
  627. * @param on true to enable SO_LINGER, false to disable
  628. * @param linger The SO_LINGER timeout in hundreths of a second or -1 if
  629. * SO_LINGER not set.
  630. *
  631. * @exception SocketException If an error occurs or Socket not connected
  632. * @exception IllegalArgumentException If linger is negative
  633. *
  634. * @since 1.1
  635. */
  636. public void setSoLinger(boolean on, int linger) throws SocketException
  637. {
  638. if (isClosed())
  639. throw new SocketException("socket is closed");
  640. if (on)
  641. {
  642. if (linger < 0)
  643. throw new IllegalArgumentException("SO_LINGER must be >= 0");
  644. if (linger > 65535)
  645. linger = 65535;
  646. getImpl().setOption(SocketOptions.SO_LINGER, new Integer(linger));
  647. }
  648. else
  649. getImpl().setOption(SocketOptions.SO_LINGER, Boolean.valueOf(false));
  650. }
  651. /**
  652. * Returns the value of the SO_LINGER option on the socket. If the
  653. * SO_LINGER option is set on a socket and there is still data waiting to
  654. * be sent when the socket is closed, then the close operation will block
  655. * until either that data is delivered or until the timeout period
  656. * expires. This method either returns the timeouts (in hundredths of
  657. * of a second (platform specific?)) if SO_LINGER is set, or -1 if
  658. * SO_LINGER is not set.
  659. *
  660. * @return The SO_LINGER timeout in hundreths of a second or -1
  661. * if SO_LINGER not set
  662. *
  663. * @exception SocketException If an error occurs or Socket is not connected
  664. *
  665. * @since 1.1
  666. */
  667. public int getSoLinger() throws SocketException
  668. {
  669. if (isClosed())
  670. throw new SocketException("socket is closed");
  671. Object linger = getImpl().getOption(SocketOptions.SO_LINGER);
  672. if (linger instanceof Integer)
  673. return (((Integer) linger).intValue());
  674. else
  675. return -1;
  676. }
  677. /**
  678. * Sends urgent data through the socket
  679. *
  680. * @param data The data to send.
  681. * Only the lowest eight bits of data are sent
  682. *
  683. * @exception IOException If an error occurs
  684. *
  685. * @since 1.4
  686. */
  687. public void sendUrgentData(int data) throws IOException
  688. {
  689. if (isClosed())
  690. throw new SocketException("socket is closed");
  691. getImpl().sendUrgentData(data);
  692. }
  693. /**
  694. * Enables/disables the SO_OOBINLINE option
  695. *
  696. * @param on True if SO_OOBLINE should be enabled
  697. *
  698. * @exception SocketException If an error occurs
  699. *
  700. * @since 1.4
  701. */
  702. public void setOOBInline(boolean on) throws SocketException
  703. {
  704. if (isClosed())
  705. throw new SocketException("socket is closed");
  706. getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));
  707. }
  708. /**
  709. * Returns the current setting of the SO_OOBINLINE option for this socket
  710. *
  711. * @return True if SO_OOBINLINE is set, false otherwise.
  712. *
  713. * @exception SocketException If an error occurs
  714. *
  715. * @since 1.4
  716. */
  717. public boolean getOOBInline() throws SocketException
  718. {
  719. if (isClosed())
  720. throw new SocketException("socket is closed");
  721. Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE);
  722. if (buf instanceof Boolean)
  723. return (((Boolean) buf).booleanValue());
  724. else
  725. throw new SocketException("Internal Error: Unexpected type");
  726. }
  727. /**
  728. * Sets the value of the SO_TIMEOUT option on the socket. If this value
  729. * is set, and an read/write is performed that does not complete within
  730. * the timeout period, a short count is returned (or an EWOULDBLOCK signal
  731. * would be sent in Unix if no data had been read). A value of 0 for
  732. * this option implies that there is no timeout (ie, operations will
  733. * block forever). On systems that have separate read and write timeout
  734. * values, this method returns the read timeout. This
  735. * value is in milliseconds.
  736. *
  737. * @param timeout The length of the timeout in milliseconds, or
  738. * 0 to indicate no timeout.
  739. *
  740. * @exception SocketException If an error occurs or Socket not connected
  741. *
  742. * @since 1.1
  743. */
  744. public synchronized void setSoTimeout(int timeout) throws SocketException
  745. {
  746. if (isClosed())
  747. throw new SocketException("socket is closed");
  748. if (timeout < 0)
  749. throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
  750. getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
  751. }
  752. /**
  753. * Returns the value of the SO_TIMEOUT option on the socket. If this value
  754. * is set, and an read/write is performed that does not complete within
  755. * the timeout period, a short count is returned (or an EWOULDBLOCK signal
  756. * would be sent in Unix if no data had been read). A value of 0 for
  757. * this option implies that there is no timeout (ie, operations will
  758. * block forever). On systems that have separate read and write timeout
  759. * values, this method returns the read timeout. This
  760. * value is in thousandths of a second (implementation specific?).
  761. *
  762. * @return The length of the timeout in thousandth's of a second or 0
  763. * if not set
  764. *
  765. * @exception SocketException If an error occurs or Socket not connected
  766. *
  767. * @since 1.1
  768. */
  769. public synchronized int getSoTimeout() throws SocketException
  770. {
  771. if (isClosed())
  772. throw new SocketException("socket is closed");
  773. Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT);
  774. if (timeout instanceof Integer)
  775. return (((Integer) timeout).intValue());
  776. else
  777. return 0;
  778. }
  779. /**
  780. * This method sets the value for the system level socket option
  781. * SO_SNDBUF to the specified value. Note that valid values for this
  782. * option are specific to a given operating system.
  783. *
  784. * @param size The new send buffer size.
  785. *
  786. * @exception SocketException If an error occurs or Socket not connected
  787. * @exception IllegalArgumentException If size is 0 or negative
  788. *
  789. * @since 1.2
  790. */
  791. public void setSendBufferSize(int size) throws SocketException
  792. {
  793. if (isClosed())
  794. throw new SocketException("socket is closed");
  795. if (size <= 0)
  796. throw new IllegalArgumentException("SO_SNDBUF value must be > 0");
  797. getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
  798. }
  799. /**
  800. * This method returns the value of the system level socket option
  801. * SO_SNDBUF, which is used by the operating system to tune buffer
  802. * sizes for data transfers.
  803. *
  804. * @return The send buffer size.
  805. *
  806. * @exception SocketException If an error occurs or socket not connected
  807. *
  808. * @since 1.2
  809. */
  810. public int getSendBufferSize() throws SocketException
  811. {
  812. if (isClosed())
  813. throw new SocketException("socket is closed");
  814. Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
  815. if (buf instanceof Integer)
  816. return (((Integer) buf).intValue());
  817. else
  818. throw new SocketException("Internal Error: Unexpected type");
  819. }
  820. /**
  821. * This method sets the value for the system level socket option
  822. * SO_RCVBUF to the specified value. Note that valid values for this
  823. * option are specific to a given operating system.
  824. *
  825. * @param size The new receive buffer size.
  826. *
  827. * @exception SocketException If an error occurs or Socket is not connected
  828. * @exception IllegalArgumentException If size is 0 or negative
  829. *
  830. * @since 1.2
  831. */
  832. public void setReceiveBufferSize(int size) throws SocketException
  833. {
  834. if (isClosed())
  835. throw new SocketException("socket is closed");
  836. if (size <= 0)
  837. throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
  838. getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
  839. }
  840. /**
  841. * This method returns the value of the system level socket option
  842. * SO_RCVBUF, which is used by the operating system to tune buffer
  843. * sizes for data transfers.
  844. *
  845. * @return The receive buffer size.
  846. *
  847. * @exception SocketException If an error occurs or Socket is not connected
  848. *
  849. * @since 1.2
  850. */
  851. public int getReceiveBufferSize() throws SocketException
  852. {
  853. if (isClosed())
  854. throw new SocketException("socket is closed");
  855. Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
  856. if (buf instanceof Integer)
  857. return (((Integer) buf).intValue());
  858. else
  859. throw new SocketException("Internal Error: Unexpected type");
  860. }
  861. /**
  862. * This method sets the value for the socket level socket option
  863. * SO_KEEPALIVE.
  864. *
  865. * @param on True if SO_KEEPALIVE should be enabled
  866. *
  867. * @exception SocketException If an error occurs or Socket is not connected
  868. *
  869. * @since 1.3
  870. */
  871. public void setKeepAlive(boolean on) throws SocketException
  872. {
  873. if (isClosed())
  874. throw new SocketException("socket is closed");
  875. getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
  876. }
  877. /**
  878. * This method returns the value of the socket level socket option
  879. * SO_KEEPALIVE.
  880. *
  881. * @return The setting
  882. *
  883. * @exception SocketException If an error occurs or Socket is not connected
  884. *
  885. * @since 1.3
  886. */
  887. public boolean getKeepAlive() throws SocketException
  888. {
  889. if (isClosed())
  890. throw new SocketException("socket is closed");
  891. Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE);
  892. if (buf instanceof Boolean)
  893. return (((Boolean) buf).booleanValue());
  894. else
  895. throw new SocketException("Internal Error: Unexpected type");
  896. }
  897. /**
  898. * Closes the socket.
  899. *
  900. * @exception IOException If an error occurs
  901. */
  902. public synchronized void close() throws IOException
  903. {
  904. if (isClosed())
  905. return;
  906. getImpl().close();
  907. impl = null;
  908. bound = false;
  909. if (getChannel() != null)
  910. getChannel().close();
  911. }
  912. /**
  913. * Converts this <code>Socket</code> to a <code>String</code>.
  914. *
  915. * @return The <code>String</code> representation of this <code>Socket</code>
  916. */
  917. public String toString()
  918. {
  919. try
  920. {
  921. if (isConnected())
  922. return ("Socket[addr=" + getImpl().getInetAddress() + ",port="
  923. + getImpl().getPort() + ",localport="
  924. + getImpl().getLocalPort() + "]");
  925. }
  926. catch (SocketException e)
  927. {
  928. // This cannot happen as we are connected.
  929. }
  930. return "Socket[unconnected]";
  931. }
  932. /**
  933. * Sets the <code>SocketImplFactory</code>. This may be done only once per
  934. * virtual machine. Subsequent attempts will generate a
  935. * <code>SocketException</code>. Note that a <code>SecurityManager</code>
  936. * check is made prior to setting the factory. If
  937. * insufficient privileges exist to set the factory, then an
  938. * <code>IOException</code> will be thrown.
  939. *
  940. * @param fac the factory to set
  941. *
  942. * @exception SecurityException If the <code>SecurityManager</code> does
  943. * not allow this operation.
  944. * @exception SocketException If the SocketImplFactory is already defined
  945. * @exception IOException If any other error occurs
  946. */
  947. public static synchronized void setSocketImplFactory(SocketImplFactory fac)
  948. throws IOException
  949. {
  950. // See if already set
  951. // if (factory != null)
  952. // throw new SocketException("SocketImplFactory already defined");
  953. if (fac == null)
  954. throw new SocketException("SocketImplFactory cannot be null");
  955. if (factory != null && fac != factory)
  956. throw new SocketException("SocketImplFactory already defined");
  957. factory = fac;
  958. }
  959. /**
  960. * Closes the input side of the socket stream.
  961. *
  962. * @exception IOException If an error occurs.
  963. *
  964. * @since 1.3
  965. */
  966. public void shutdownInput() throws IOException
  967. {
  968. if (isClosed())
  969. throw new SocketException("socket is closed");
  970. getImpl().shutdownInput();
  971. inputShutdown = true;
  972. }
  973. /**
  974. * Closes the output side of the socket stream.
  975. *
  976. * @exception IOException If an error occurs.
  977. *
  978. * @since 1.3
  979. */
  980. public void shutdownOutput() throws IOException
  981. {
  982. if (isClosed())
  983. throw new SocketException("socket is closed");
  984. getImpl().shutdownOutput();
  985. outputShutdown = true;
  986. }
  987. /**
  988. * Returns the socket channel associated with this socket.
  989. *
  990. * @return the associated socket channel,
  991. * null if no associated channel exists
  992. *
  993. * @since 1.4
  994. */
  995. public SocketChannel getChannel()
  996. {
  997. return null;
  998. }
  999. /**
  1000. * Checks if the SO_REUSEADDR option is enabled
  1001. *
  1002. * @return True if SO_REUSEADDR is set, false otherwise.
  1003. *
  1004. * @exception SocketException If an error occurs
  1005. *
  1006. * @since 1.4
  1007. */
  1008. public boolean getReuseAddress() throws SocketException
  1009. {
  1010. if (isClosed())
  1011. throw new SocketException("socket is closed");
  1012. Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR);
  1013. if (! (reuseaddr instanceof Boolean))
  1014. throw new SocketException("Internal Error");
  1015. return ((Boolean) reuseaddr).booleanValue();
  1016. }
  1017. /**
  1018. * Enables/Disables the SO_REUSEADDR option
  1019. *
  1020. * @param reuseAddress true if SO_REUSEADDR should be enabled,
  1021. * false otherwise
  1022. *
  1023. * @exception SocketException If an error occurs
  1024. *
  1025. * @since 1.4
  1026. */
  1027. public void setReuseAddress(boolean reuseAddress) throws SocketException
  1028. {
  1029. if (isClosed())
  1030. throw new SocketException("socket is closed");
  1031. getImpl().setOption(SocketOptions.SO_REUSEADDR,
  1032. Boolean.valueOf(reuseAddress));
  1033. }
  1034. /**
  1035. * Returns the current traffic class
  1036. *
  1037. * @return The current traffic class.
  1038. *
  1039. * @exception SocketException If an error occurs
  1040. *
  1041. * @see Socket#setTrafficClass(int tc)
  1042. *
  1043. * @since 1.4
  1044. */
  1045. public int getTrafficClass() throws SocketException
  1046. {
  1047. if (isClosed())
  1048. throw new SocketException("socket is closed");
  1049. Object obj = getImpl().getOption(SocketOptions.IP_TOS);
  1050. if (obj instanceof Integer)
  1051. return ((Integer) obj).intValue();
  1052. else
  1053. throw new SocketException("Unexpected type");
  1054. }
  1055. /**
  1056. * Sets the traffic class value
  1057. *
  1058. * @param tc The traffic class
  1059. *
  1060. * @exception SocketException If an error occurs
  1061. * @exception IllegalArgumentException If tc value is illegal
  1062. *
  1063. * @see Socket#getTrafficClass()
  1064. *
  1065. * @since 1.4
  1066. */
  1067. public void setTrafficClass(int tc) throws SocketException
  1068. {
  1069. if (isClosed())
  1070. throw new SocketException("socket is closed");
  1071. if (tc < 0 || tc > 255)
  1072. throw new IllegalArgumentException();
  1073. getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
  1074. }
  1075. /**
  1076. * Checks if the socket is connected
  1077. *
  1078. * @return True if socket is connected, false otherwise.
  1079. *
  1080. * @since 1.4
  1081. */
  1082. public boolean isConnected()
  1083. {
  1084. try
  1085. {
  1086. if (getImpl() == null)
  1087. return false;
  1088. return getImpl().getInetAddress() != null;
  1089. }
  1090. catch (SocketException e)
  1091. {
  1092. return false;
  1093. }
  1094. }
  1095. /**
  1096. * Checks if the socket is already bound.
  1097. *
  1098. * @return True if socket is bound, false otherwise.
  1099. *
  1100. * @since 1.4
  1101. */
  1102. public boolean isBound()
  1103. {
  1104. return bound;
  1105. }
  1106. /**
  1107. * Checks if the socket is closed.
  1108. *
  1109. * @return True if socket is closed, false otherwise.
  1110. *
  1111. * @since 1.4
  1112. */
  1113. public boolean isClosed()
  1114. {
  1115. return impl == null;
  1116. }
  1117. /**
  1118. * Checks if the socket's input stream is shutdown
  1119. *
  1120. * @return True if input is shut down.
  1121. *
  1122. * @since 1.4
  1123. */
  1124. public boolean isInputShutdown()
  1125. {
  1126. return inputShutdown;
  1127. }
  1128. /**
  1129. * Checks if the socket's output stream is shutdown
  1130. *
  1131. * @return True if output is shut down.
  1132. *
  1133. * @since 1.4
  1134. */
  1135. public boolean isOutputShutdown()
  1136. {
  1137. return outputShutdown;
  1138. }
  1139. }