1. /*
  2. * @(#)DatagramSocket.java 1.96 04/03/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.net;
  8. import java.io.FileDescriptor;
  9. import java.io.IOException;
  10. import java.io.InterruptedIOException;
  11. import java.nio.channels.DatagramChannel;
  12. import java.security.AccessController;
  13. import java.security.PrivilegedExceptionAction;
  14. /**
  15. * This class represents a socket for sending and receiving datagram packets.
  16. *
  17. * <p>A datagram socket is the sending or receiving point for a packet
  18. * delivery service. Each packet sent or received on a datagram socket
  19. * is individually addressed and routed. Multiple packets sent from
  20. * one machine to another may be routed differently, and may arrive in
  21. * any order.
  22. *
  23. * <p>UDP broadcasts sends are always enabled on a DatagramSocket.
  24. * In order to receive broadcast packets a DatagramSocket
  25. * should be bound to the wildcard address. In some
  26. * implementations, broadcast packets may also be received when
  27. * a DatagramSocket is bound to a more specific address.
  28. * <p>
  29. * Example:
  30. * <code>
  31. * DatagramSocket s = new DatagramSocket(null);
  32. * s.bind(new InetSocketAddress(8888));
  33. * </code>
  34. * Which is equivalent to:
  35. * <code>
  36. * DatagramSocket s = new DatagramSocket(8888);
  37. * </code>
  38. * Both cases will create a DatagramSocket able to receive broadcasts on
  39. * UDP port 8888.
  40. *
  41. * @author Pavani Diwanji
  42. * @version 1.96, 03/05/04
  43. * @see java.net.DatagramPacket
  44. * @see java.nio.channels.DatagramChannel
  45. * @since JDK1.0
  46. */
  47. public
  48. class DatagramSocket {
  49. /**
  50. * Various states of this socket.
  51. */
  52. private boolean created = false;
  53. private boolean bound = false;
  54. private boolean closed = false;
  55. private Object closeLock = new Object();
  56. /*
  57. * The implementation of this DatagramSocket.
  58. */
  59. DatagramSocketImpl impl;
  60. /**
  61. * Are we using an older DatagramSocketImpl?
  62. */
  63. boolean oldImpl = false;
  64. /*
  65. * Connection state:
  66. * ST_NOT_CONNECTED = socket not connected
  67. * ST_CONNECTED = socket connected
  68. * ST_CONNECTED_NO_IMPL = socket connected but not at impl level
  69. */
  70. static final int ST_NOT_CONNECTED = 0;
  71. static final int ST_CONNECTED = 1;
  72. static final int ST_CONNECTED_NO_IMPL = 2;
  73. int connectState = ST_NOT_CONNECTED;
  74. /*
  75. * Connected address & port
  76. */
  77. InetAddress connectedAddress = null;
  78. int connectedPort = -1;
  79. /**
  80. * Connects this socket to a remote socket address (IP address + port number).
  81. * Binds socket if not already bound.
  82. * <p>
  83. * @param addr The remote address.
  84. * @param port The remote port
  85. * @throws SocketException if binding the socket fails.
  86. */
  87. private synchronized void connectInternal(InetAddress address, int port) throws SocketException {
  88. if (port < 0 || port > 0xFFFF) {
  89. throw new IllegalArgumentException("connect: " + port);
  90. }
  91. if (address == null) {
  92. throw new IllegalArgumentException("connect: null address");
  93. }
  94. if (isClosed())
  95. return;
  96. SecurityManager security = System.getSecurityManager();
  97. if (security != null) {
  98. if (address.isMulticastAddress()) {
  99. security.checkMulticast(address);
  100. } else {
  101. security.checkConnect(address.getHostAddress(), port);
  102. security.checkAccept(address.getHostAddress(), port);
  103. }
  104. }
  105. if (!isBound())
  106. bind(new InetSocketAddress(0));
  107. // old impls do not support connect/disconnect
  108. if (oldImpl) {
  109. connectState = ST_CONNECTED_NO_IMPL;
  110. } else {
  111. try {
  112. getImpl().connect(address, port);
  113. // socket is now connected by the impl
  114. connectState = ST_CONNECTED;
  115. } catch (SocketException se) {
  116. // connection will be emulated by DatagramSocket
  117. connectState = ST_CONNECTED_NO_IMPL;
  118. }
  119. }
  120. connectedAddress = address;
  121. connectedPort = port;
  122. }
  123. /**
  124. * Constructs a datagram socket and binds it to any available port
  125. * on the local host machine. The socket will be bound to the wildcard
  126. * address, an IP address chosen by the kernel.
  127. *
  128. * <p>If there is a security manager,
  129. * its <code>checkListen</code> method is first called
  130. * with 0 as its argument to ensure the operation is allowed.
  131. * This could result in a SecurityException.
  132. *
  133. * @exception SocketException if the socket could not be opened,
  134. * or the socket could not bind to the specified local port.
  135. * @exception SecurityException if a security manager exists and its
  136. * <code>checkListen</code> method doesn't allow the operation.
  137. *
  138. * @see SecurityManager#checkListen
  139. */
  140. public DatagramSocket() throws SocketException {
  141. // create a datagram socket.
  142. createImpl();
  143. try {
  144. bind(new InetSocketAddress(0));
  145. } catch (SocketException se) {
  146. throw se;
  147. } catch(IOException e) {
  148. throw new SocketException(e.getMessage());
  149. }
  150. }
  151. /**
  152. * Creates an unbound datagram socket with the specified
  153. * DatagramSocketImpl.
  154. *
  155. * @param impl an instance of a <B>DatagramSocketImpl</B>
  156. * the subclass wishes to use on the DatagramSocket.
  157. * @since 1.4
  158. */
  159. protected DatagramSocket(DatagramSocketImpl impl) {
  160. if (impl == null)
  161. throw new NullPointerException();
  162. this.impl = impl;
  163. checkOldImpl();
  164. }
  165. /**
  166. * Creates a datagram socket, bound to the specified local
  167. * socket address.
  168. * <p>
  169. * If, if the address is <code>null</code>, creates an unbound socket.
  170. * <p>
  171. * <p>If there is a security manager,
  172. * its <code>checkListen</code> method is first called
  173. * with the port from the socket address
  174. * as its argument to ensure the operation is allowed.
  175. * This could result in a SecurityException.
  176. *
  177. * @param bindaddr local socket address to bind, or <code>null</code>
  178. * for an unbound socket.
  179. *
  180. * @exception SocketException if the socket could not be opened,
  181. * or the socket could not bind to the specified local port.
  182. * @exception SecurityException if a security manager exists and its
  183. * <code>checkListen</code> method doesn't allow the operation.
  184. *
  185. * @see SecurityManager#checkListen
  186. * @since 1.4
  187. */
  188. public DatagramSocket(SocketAddress bindaddr) throws SocketException {
  189. // create a datagram socket.
  190. createImpl();
  191. if (bindaddr != null) {
  192. bind(bindaddr);
  193. }
  194. }
  195. /**
  196. * Constructs a datagram socket and binds it to the specified port
  197. * on the local host machine. The socket will be bound to the wildcard
  198. * address, an IP address chosen by the kernel.
  199. *
  200. * <p>If there is a security manager,
  201. * its <code>checkListen</code> method is first called
  202. * with the <code>port</code> argument
  203. * as its argument to ensure the operation is allowed.
  204. * This could result in a SecurityException.
  205. *
  206. * @param port port to use.
  207. * @exception SocketException if the socket could not be opened,
  208. * or the socket could not bind to the specified local port.
  209. * @exception SecurityException if a security manager exists and its
  210. * <code>checkListen</code> method doesn't allow the operation.
  211. *
  212. * @see SecurityManager#checkListen
  213. */
  214. public DatagramSocket(int port) throws SocketException {
  215. this(port, null);
  216. }
  217. /**
  218. * Creates a datagram socket, bound to the specified local
  219. * address. The local port must be between 0 and 65535 inclusive.
  220. * If the IP address is 0.0.0.0, the socket will be bound to the
  221. * wildcard address, an IP address chosen by the kernel.
  222. *
  223. * <p>If there is a security manager,
  224. * its <code>checkListen</code> method is first called
  225. * with the <code>port</code> argument
  226. * as its argument to ensure the operation is allowed.
  227. * This could result in a SecurityException.
  228. *
  229. * @param port local port to use
  230. * @param laddr local address to bind
  231. *
  232. * @exception SocketException if the socket could not be opened,
  233. * or the socket could not bind to the specified local port.
  234. * @exception SecurityException if a security manager exists and its
  235. * <code>checkListen</code> method doesn't allow the operation.
  236. *
  237. * @see SecurityManager#checkListen
  238. * @since JDK1.1
  239. */
  240. public DatagramSocket(int port, InetAddress laddr) throws SocketException {
  241. this(new InetSocketAddress(laddr, port));
  242. }
  243. private void checkOldImpl() {
  244. if (impl == null)
  245. return;
  246. // DatagramSocketImpl.peekdata() is a protected method, therefore we need to use
  247. // getDeclaredMethod, therefore we need permission to access the member
  248. try {
  249. AccessController.doPrivileged(new PrivilegedExceptionAction() {
  250. public Object run() throws NoSuchMethodException {
  251. Class[] cl = new Class[1];
  252. cl[0] = DatagramPacket.class;
  253. impl.getClass().getDeclaredMethod("peekData", cl);
  254. return null;
  255. }
  256. });
  257. } catch (java.security.PrivilegedActionException e) {
  258. oldImpl = true;
  259. }
  260. }
  261. static Class implClass = null;
  262. void createImpl() throws SocketException {
  263. if (impl == null) {
  264. if (factory != null) {
  265. impl = factory.createDatagramSocketImpl();
  266. checkOldImpl();
  267. } else {
  268. if (implClass == null) {
  269. String prefix = null;
  270. try {
  271. prefix = (String) AccessController.doPrivileged(
  272. new sun.security.action.GetPropertyAction("impl.prefix", "Plain"));
  273. implClass = Class.forName("java.net."+prefix+"DatagramSocketImpl");
  274. } catch (Exception e) {
  275. System.err.println("Can't find class: java.net." +
  276. prefix +
  277. "DatagramSocketImpl: check impl.prefix property");
  278. }
  279. if (implClass == null)
  280. implClass = java.net.PlainDatagramSocketImpl.class;
  281. }
  282. try {
  283. impl = (DatagramSocketImpl) implClass.newInstance();
  284. } catch (Exception e) {
  285. throw new SocketException("can't instantiate DatagramSocketImpl");
  286. }
  287. // No need to do a checkOldImpl() here, we know it's an up to date
  288. // SocketImpl!
  289. if (!(impl instanceof java.net.PlainDatagramSocketImpl))
  290. checkOldImpl();
  291. }
  292. }
  293. // creates a udp socket
  294. impl.create();
  295. created = true;
  296. }
  297. /**
  298. * Get the <code>DatagramSocketImpl</code> attached to this socket,
  299. * creating it if necessary.
  300. *
  301. * @return the <code>DatagramSocketImpl</code> attached to that
  302. * DatagramSocket
  303. * @throws SocketException if creation fails.
  304. * @since 1.4
  305. */
  306. DatagramSocketImpl getImpl() throws SocketException {
  307. if (!created)
  308. createImpl();
  309. return impl;
  310. }
  311. /**
  312. * Binds this DatagramSocket to a specific address & port.
  313. * <p>
  314. * If the address is <code>null</code>, then the system will pick up
  315. * an ephemeral port and a valid local address to bind the socket.
  316. *<p>
  317. * @param addr The address & port to bind to.
  318. * @throws SocketException if any error happens during the bind, or if the
  319. * socket is already bound.
  320. * @throws SecurityException if a security manager exists and its
  321. * <code>checkListen</code> method doesn't allow the operation.
  322. * @throws IllegalArgumentException if addr is a SocketAddress subclass
  323. * not supported by this socket.
  324. * @since 1.4
  325. */
  326. public synchronized void bind(SocketAddress addr) throws SocketException {
  327. if (isClosed())
  328. throw new SocketException("Socket is closed");
  329. if (isBound())
  330. throw new SocketException("already bound");
  331. if (addr == null)
  332. addr = new InetSocketAddress(0);
  333. if (!(addr instanceof InetSocketAddress))
  334. throw new IllegalArgumentException("Unsupported address type!");
  335. InetSocketAddress epoint = (InetSocketAddress) addr;
  336. if (epoint.isUnresolved())
  337. throw new SocketException("Unresolved address");
  338. SecurityManager sec = System.getSecurityManager();
  339. if (sec != null) {
  340. sec.checkListen(epoint.getPort());
  341. }
  342. try {
  343. getImpl().bind(epoint.getPort(),
  344. epoint.getAddress());
  345. } catch (SocketException e) {
  346. getImpl().close();
  347. throw e;
  348. }
  349. bound = true;
  350. }
  351. /**
  352. * Connects the socket to a remote address for this socket. When a
  353. * socket is connected to a remote address, packets may only be
  354. * sent to or received from that address. By default a datagram
  355. * socket is not connected.
  356. *
  357. * <p>If the remote destination to which the socket is connected does not
  358. * exist, or is otherwise unreachable, and if an ICMP destination unreachable
  359. * packet has been received for that address, then a subsequent call to
  360. * send or receive may throw a PortUnreachableException. Note, there is no
  361. * guarantee that the exception will be thrown.
  362. *
  363. * <p>A caller's permission to send and receive datagrams to a
  364. * given host and port are checked at connect time. When a socket
  365. * is connected, receive and send <b>will not
  366. * perform any security checks</b> on incoming and outgoing
  367. * packets, other than matching the packet's and the socket's
  368. * address and port. On a send operation, if the packet's address
  369. * is set and the packet's address and the socket's address do not
  370. * match, an IllegalArgumentException will be thrown. A socket
  371. * connected to a multicast address may only be used to send packets.
  372. *
  373. * @param address the remote address for the socket
  374. *
  375. * @param port the remote port for the socket.
  376. *
  377. * @exception IllegalArgumentException if the address is null,
  378. * or the port is out of range.
  379. *
  380. * @exception SecurityException if the caller is not allowed to
  381. * send datagrams to and receive datagrams from the address and port.
  382. *
  383. * @see #disconnect
  384. * @see #send
  385. * @see #receive
  386. */
  387. public void connect(InetAddress address, int port) {
  388. try {
  389. connectInternal(address, port);
  390. } catch (SocketException se) {
  391. throw new Error("connect failed", se);
  392. }
  393. }
  394. /**
  395. * Connects this socket to a remote socket address (IP address + port number).
  396. * <p>
  397. * @param addr The remote address.
  398. * @throws SocketException if the connect fails
  399. * @throws IllegalArgumentException if addr is null or addr is a SocketAddress
  400. * subclass not supported by this socket
  401. * @since 1.4
  402. * @see #connect
  403. */
  404. public void connect(SocketAddress addr) throws SocketException {
  405. if (addr == null)
  406. throw new IllegalArgumentException("Address can't be null");
  407. if (!(addr instanceof InetSocketAddress))
  408. throw new IllegalArgumentException("Unsupported address type");
  409. InetSocketAddress epoint = (InetSocketAddress) addr;
  410. if (epoint.isUnresolved())
  411. throw new SocketException("Unresolved address");
  412. connectInternal(epoint.getAddress(), epoint.getPort());
  413. }
  414. /**
  415. * Disconnects the socket. This does nothing if the socket is not
  416. * connected.
  417. *
  418. * @see #connect
  419. */
  420. public void disconnect() {
  421. synchronized (this) {
  422. if (isClosed())
  423. return;
  424. if (connectState == ST_CONNECTED) {
  425. impl.disconnect ();
  426. }
  427. connectedAddress = null;
  428. connectedPort = -1;
  429. connectState = ST_NOT_CONNECTED;
  430. }
  431. }
  432. /**
  433. * Returns the binding state of the socket.
  434. *
  435. * @return true if the socket succesfuly bound to an address
  436. * @since 1.4
  437. */
  438. public boolean isBound() {
  439. return bound;
  440. }
  441. /**
  442. * Returns the connection state of the socket.
  443. *
  444. * @return true if the socket succesfuly connected to a server
  445. * @since 1.4
  446. */
  447. public boolean isConnected() {
  448. return connectState != ST_NOT_CONNECTED;
  449. }
  450. /**
  451. * Returns the address to which this socket is connected. Returns null
  452. * if the socket is not connected.
  453. *
  454. * @return the address to which this socket is connected.
  455. */
  456. public InetAddress getInetAddress() {
  457. return connectedAddress;
  458. }
  459. /**
  460. * Returns the port for this socket. Returns -1 if the socket is not
  461. * connected.
  462. *
  463. * @return the port to which this socket is connected.
  464. */
  465. public int getPort() {
  466. return connectedPort;
  467. }
  468. /**
  469. * Returns the address of the endpoint this socket is connected to, or
  470. * <code>null</code> if it is unconnected.
  471. * @return a <code>SocketAddress</code> representing the remote
  472. * endpoint of this socket, or <code>null</code> if it is
  473. * not connected yet.
  474. * @see #getInetAddress()
  475. * @see #getPort()
  476. * @see #connect(SocketAddress)
  477. * @since 1.4
  478. */
  479. public SocketAddress getRemoteSocketAddress() {
  480. if (!isConnected())
  481. return null;
  482. return new InetSocketAddress(getInetAddress(), getPort());
  483. }
  484. /**
  485. * Returns the address of the endpoint this socket is bound to, or
  486. * <code>null</code> if it is not bound yet.
  487. *
  488. * @return a <code>SocketAddress</code> representing the local endpoint of this
  489. * socket, or <code>null</code> if it is not bound yet.
  490. * @see #getLocalAddress()
  491. * @see #getLocalPort()
  492. * @see #bind(SocketAddress)
  493. * @since 1.4
  494. */
  495. public SocketAddress getLocalSocketAddress() {
  496. if (!isBound())
  497. return null;
  498. return new InetSocketAddress(getLocalAddress(), getLocalPort());
  499. }
  500. /**
  501. * Sends a datagram packet from this socket. The
  502. * <code>DatagramPacket</code> includes information indicating the
  503. * data to be sent, its length, the IP address of the remote host,
  504. * and the port number on the remote host.
  505. *
  506. * <p>If there is a security manager, and the socket is not currently
  507. * connected to a remote address, this method first performs some
  508. * security checks. First, if <code>p.getAddress().isMulticastAddress()</code>
  509. * is true, this method calls the
  510. * security manager's <code>checkMulticast</code> method
  511. * with <code>p.getAddress()</code> as its argument.
  512. * If the evaluation of that expression is false,
  513. * this method instead calls the security manager's
  514. * <code>checkConnect</code> method with arguments
  515. * <code>p.getAddress().getHostAddress()</code> and
  516. * <code>p.getPort()</code>. Each call to a security manager method
  517. * could result in a SecurityException if the operation is not allowed.
  518. *
  519. * @param p the <code>DatagramPacket</code> to be sent.
  520. *
  521. * @exception IOException if an I/O error occurs.
  522. * @exception SecurityException if a security manager exists and its
  523. * <code>checkMulticast</code> or <code>checkConnect</code>
  524. * method doesn't allow the send.
  525. * @exception PortUnreachableException may be thrown if the socket is connected
  526. * to a currently unreachable destination. Note, there is no
  527. * guarantee that the exception will be thrown.
  528. * @exception java.nio.channels.IllegalBlockingModeException
  529. * if this socket has an associated channel,
  530. * and the channel is in non-blocking mode.
  531. *
  532. * @see java.net.DatagramPacket
  533. * @see SecurityManager#checkMulticast(InetAddress)
  534. * @see SecurityManager#checkConnect
  535. * @revised 1.4
  536. * @spec JSR-51
  537. */
  538. public void send(DatagramPacket p) throws IOException {
  539. InetAddress packetAddress = null;
  540. synchronized (p) {
  541. if (isClosed())
  542. throw new SocketException("Socket is closed");
  543. if (connectState == ST_NOT_CONNECTED) {
  544. // check the address is ok wiht the security manager on every send.
  545. SecurityManager security = System.getSecurityManager();
  546. // The reason you want to synchronize on datagram packet
  547. // is because you dont want an applet to change the address
  548. // while you are trying to send the packet for example
  549. // after the security check but before the send.
  550. if (security != null) {
  551. if (p.getAddress().isMulticastAddress()) {
  552. security.checkMulticast(p.getAddress());
  553. } else {
  554. security.checkConnect(p.getAddress().getHostAddress(),
  555. p.getPort());
  556. }
  557. }
  558. } else {
  559. // we're connected
  560. packetAddress = p.getAddress();
  561. if (packetAddress == null) {
  562. p.setAddress(connectedAddress);
  563. p.setPort(connectedPort);
  564. } else if ((!packetAddress.equals(connectedAddress)) ||
  565. p.getPort() != connectedPort) {
  566. throw new IllegalArgumentException("connected address " +
  567. "and packet address" +
  568. " differ");
  569. }
  570. }
  571. // Check whether the socket is bound
  572. if (!isBound())
  573. bind(new InetSocketAddress(0));
  574. // call the method to send
  575. getImpl().send(p);
  576. }
  577. }
  578. /**
  579. * Receives a datagram packet from this socket. When this method
  580. * returns, the <code>DatagramPacket</code>'s buffer is filled with
  581. * the data received. The datagram packet also contains the sender's
  582. * IP address, and the port number on the sender's machine.
  583. * <p>
  584. * This method blocks until a datagram is received. The
  585. * <code>length</code> field of the datagram packet object contains
  586. * the length of the received message. If the message is longer than
  587. * the packet's length, the message is truncated.
  588. * <p>
  589. * If there is a security manager, a packet cannot be received if the
  590. * security manager's <code>checkAccept</code> method
  591. * does not allow it.
  592. *
  593. * @param p the <code>DatagramPacket</code> into which to place
  594. * the incoming data.
  595. * @exception IOException if an I/O error occurs.
  596. * @exception SocketTimeoutException if setSoTimeout was previously called
  597. * and the timeout has expired.
  598. * @exception PortUnreachableException may be thrown if the socket is connected
  599. * to a currently unreachable destination. Note, there is no guarantee that the
  600. * exception will be thrown.
  601. * @exception java.nio.channels.IllegalBlockingModeException
  602. * if this socket has an associated channel,
  603. * and the channel is in non-blocking mode.
  604. * @see java.net.DatagramPacket
  605. * @see java.net.DatagramSocket
  606. * @revised 1.4
  607. * @spec JSR-51
  608. */
  609. public synchronized void receive(DatagramPacket p) throws IOException {
  610. synchronized (p) {
  611. if (!isBound())
  612. bind(new InetSocketAddress(0));
  613. if (connectState == ST_NOT_CONNECTED) {
  614. // check the address is ok with the security manager before every recv.
  615. SecurityManager security = System.getSecurityManager();
  616. if (security != null) {
  617. while(true) {
  618. String peekAd = null;
  619. int peekPort = 0;
  620. // peek at the packet to see who it is from.
  621. if (!oldImpl) {
  622. // We can use the new peekData() API
  623. DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
  624. peekPort = getImpl().peekData(peekPacket);
  625. peekAd = peekPacket.getAddress().getHostAddress();
  626. } else {
  627. InetAddress adr = new InetAddress();
  628. peekPort = getImpl().peek(adr);
  629. peekAd = adr.getHostAddress();
  630. }
  631. try {
  632. security.checkAccept(peekAd, peekPort);
  633. // security check succeeded - so now break
  634. // and recv the packet.
  635. break;
  636. } catch (SecurityException se) {
  637. // Throw away the offending packet by consuming
  638. // it in a tmp buffer.
  639. DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
  640. getImpl().receive(tmp);
  641. // silently discard the offending packet
  642. // and continue: unknown/malicious
  643. // entities on nets should not make
  644. // runtime throw security exception and
  645. // disrupt the applet by sending random
  646. // datagram packets.
  647. continue;
  648. }
  649. } // end of while
  650. }
  651. }
  652. if (connectState == ST_CONNECTED_NO_IMPL) {
  653. // We have to do the filtering the old fashioned way since
  654. // the native impl doesn't support connect or the connect
  655. // via the impl failed.
  656. boolean stop = false;
  657. while (!stop) {
  658. // peek at the packet to see who it is from.
  659. InetAddress peekAddress = new InetAddress();
  660. int peekPort = getImpl().peek(peekAddress);
  661. if ((!connectedAddress.equals(peekAddress)) ||
  662. (connectedPort != peekPort)) {
  663. // throw the packet away and silently continue
  664. DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
  665. getImpl().receive(tmp);
  666. } else {
  667. stop = true;
  668. }
  669. }
  670. }
  671. // If the security check succeeds, or the datagram is
  672. // connected then receive the packet
  673. getImpl().receive(p);
  674. }
  675. }
  676. /**
  677. * Gets the local address to which the socket is bound.
  678. *
  679. * <p>If there is a security manager, its
  680. * <code>checkConnect</code> method is first called
  681. * with the host address and <code>-1</code>
  682. * as its arguments to see if the operation is allowed.
  683. *
  684. * @see SecurityManager#checkConnect
  685. * @return the local address to which the socket is bound, or
  686. * an <code>InetAddress</code> representing any local
  687. * address if either the socket is not bound, or
  688. * the security manager <code>checkConnect</code>
  689. * method does not allow the operation
  690. * @since 1.1
  691. */
  692. public InetAddress getLocalAddress() {
  693. if (isClosed())
  694. return null;
  695. InetAddress in = null;
  696. try {
  697. in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
  698. if (in.isAnyLocalAddress()) {
  699. in = InetAddress.anyLocalAddress();
  700. }
  701. SecurityManager s = System.getSecurityManager();
  702. if (s != null) {
  703. s.checkConnect(in.getHostAddress(), -1);
  704. }
  705. } catch (Exception e) {
  706. in = InetAddress.anyLocalAddress(); // "0.0.0.0"
  707. }
  708. return in;
  709. }
  710. /**
  711. * Returns the port number on the local host to which this socket is bound.
  712. *
  713. * @return the port number on the local host to which this socket is bound.
  714. */
  715. public int getLocalPort() {
  716. if (isClosed())
  717. return -1;
  718. try {
  719. return getImpl().getLocalPort();
  720. } catch (Exception e) {
  721. return 0;
  722. }
  723. }
  724. /** Enable/disable SO_TIMEOUT with the specified timeout, in
  725. * milliseconds. With this option set to a non-zero timeout,
  726. * a call to receive() for this DatagramSocket
  727. * will block for only this amount of time. If the timeout expires,
  728. * a <B>java.net.SocketTimeoutException</B> is raised, though the
  729. * DatagramSocket is still valid. The option <B>must</B> be enabled
  730. * prior to entering the blocking operation to have effect. The
  731. * timeout must be > 0.
  732. * A timeout of zero is interpreted as an infinite timeout.
  733. *
  734. * @param timeout the specified timeout in milliseconds.
  735. * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
  736. * @since JDK1.1
  737. * @see #getSoTimeout()
  738. */
  739. public synchronized void setSoTimeout(int timeout) throws SocketException {
  740. if (isClosed())
  741. throw new SocketException("Socket is closed");
  742. getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
  743. }
  744. /**
  745. * Retrive setting for SO_TIMEOUT. 0 returns implies that the
  746. * option is disabled (i.e., timeout of infinity).
  747. *
  748. * @return the setting for SO_TIMEOUT
  749. * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
  750. * @since JDK1.1
  751. * @see #setSoTimeout(int)
  752. */
  753. public synchronized int getSoTimeout() throws SocketException {
  754. if (isClosed())
  755. throw new SocketException("Socket is closed");
  756. if (getImpl() == null)
  757. return 0;
  758. Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
  759. /* extra type safety */
  760. if (o instanceof Integer) {
  761. return ((Integer) o).intValue();
  762. } else {
  763. return 0;
  764. }
  765. }
  766. /**
  767. * Sets the SO_SNDBUF option to the specified value for this
  768. * <tt>DatagramSocket</tt>. The SO_SNDBUF option is used by the
  769. * network implementation as a hint to size the underlying
  770. * network I/O buffers. The SO_SNDBUF setting may also be used
  771. * by the network implementation to determine the maximum size
  772. * of the packet that can be sent on this socket.
  773. * <p>
  774. * As SO_SNDBUF is a hint, applications that want to verify
  775. * what size the buffer is should call {@link #getSendBufferSize()}.
  776. * <p>
  777. * Increasing the buffer size may allow multiple outgoing packets
  778. * to be queued by the network implementation when the send rate
  779. * is high.
  780. * <p>
  781. * Note: If {@link #send(DatagramPacket)} is used to send a
  782. * <code>DatagramPacket</code> that is larger than the setting
  783. * of SO_SNDBUF then it is implementation specific if the
  784. * packet is sent or discarded.
  785. *
  786. * @param size the size to which to set the send buffer
  787. * size. This value must be greater than 0.
  788. *
  789. * @exception SocketException if there is an error
  790. * in the underlying protocol, such as an UDP error.
  791. * @exception IllegalArgumentException if the value is 0 or is
  792. * negative.
  793. * @see #getSendBufferSize()
  794. */
  795. public synchronized void setSendBufferSize(int size)
  796. throws SocketException{
  797. if (!(size > 0)) {
  798. throw new IllegalArgumentException("negative send size");
  799. }
  800. if (isClosed())
  801. throw new SocketException("Socket is closed");
  802. getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
  803. }
  804. /**
  805. * Get value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>, that is the
  806. * buffer size used by the platform for output on this <tt>DatagramSocket</tt>.
  807. *
  808. * @return the value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>
  809. * @exception SocketException if there is an error in
  810. * the underlying protocol, such as an UDP error.
  811. * @see #setSendBufferSize
  812. */
  813. public synchronized int getSendBufferSize() throws SocketException {
  814. if (isClosed())
  815. throw new SocketException("Socket is closed");
  816. int result = 0;
  817. Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);
  818. if (o instanceof Integer) {
  819. result = ((Integer)o).intValue();
  820. }
  821. return result;
  822. }
  823. /**
  824. * Sets the SO_RCVBUF option to the specified value for this
  825. * <tt>DatagramSocket</tt>. The SO_RCVBUF option is used by the
  826. * the network implementation as a hint to size the underlying
  827. * network I/O buffers. The SO_RCVBUF setting may also be used
  828. * by the network implementation to determine the maximum size
  829. * of the packet that can be received on this socket.
  830. * <p>
  831. * Because SO_RCVBUF is a hint, applications that want to
  832. * verify what size the buffers were set to should call
  833. * {@link #getReceiveBufferSize()}.
  834. * <p>
  835. * Increasing SO_RCVBUF may allow the network implementation
  836. * to buffer multiple packets when packets arrive faster than
  837. * are being received using {@link #receive(DatagramPacket)}.
  838. * <p>
  839. * Note: It is implementation specific if a packet larger
  840. * than SO_RCVBUF can be received.
  841. *
  842. * @param size the size to which to set the receive buffer
  843. * size. This value must be greater than 0.
  844. *
  845. * @exception SocketException if there is an error in
  846. * the underlying protocol, such as an UDP error.
  847. * @exception IllegalArgumentException if the value is 0 or is
  848. * negative.
  849. * @see #getReceiveBufferSize()
  850. */
  851. public synchronized void setReceiveBufferSize(int size)
  852. throws SocketException{
  853. if (size <= 0) {
  854. throw new IllegalArgumentException("invalid receive size");
  855. }
  856. if (isClosed())
  857. throw new SocketException("Socket is closed");
  858. getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
  859. }
  860. /**
  861. * Get value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>, that is the
  862. * buffer size used by the platform for input on this <tt>DatagramSocket</tt>.
  863. *
  864. * @return the value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>
  865. * @exception SocketException if there is an error in the underlying protocol, such as an UDP error.
  866. * @see #setReceiveBufferSize(int)
  867. */
  868. public synchronized int getReceiveBufferSize()
  869. throws SocketException{
  870. if (isClosed())
  871. throw new SocketException("Socket is closed");
  872. int result = 0;
  873. Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);
  874. if (o instanceof Integer) {
  875. result = ((Integer)o).intValue();
  876. }
  877. return result;
  878. }
  879. /**
  880. * Enable/disable the SO_REUSEADDR socket option.
  881. * <p>
  882. * For UDP sockets it may be necessary to bind more than one
  883. * socket to the same socket address. This is typically for the
  884. * purpose of receiving multicast packets
  885. * (See {@link java.net.MulticastSocket}). The
  886. * <tt>SO_REUSEADDR</tt> socket option allows multiple
  887. * sockets to be bound to the same socket address if the
  888. * <tt>SO_REUSEADDR</tt> socket option is enabled prior
  889. * to binding the socket using {@link #bind(SocketAddress)}.
  890. * <p>
  891. * When a <tt>DatagramSocket</tt> is created the initial setting
  892. * of <tt>SO_REUSEADDR</tt> is disabled.
  893. * <p>
  894. * The behaviour when <tt>SO_REUSEADDR</tt> is enabled or
  895. * disabled after a socket is bound (See {@link #isBound()})
  896. * is not defined.
  897. *
  898. * @param on whether to enable or disable the
  899. * @exception SocketException if an error occurs enabling or
  900. * disabling the <tt>SO_RESUEADDR</tt> socket option,
  901. * or the socket is closed.
  902. * @since 1.4
  903. * @see #getReuseAddress()
  904. * @see #bind(SocketAddress)
  905. * @see #isBound()
  906. * @see #isClosed()
  907. */
  908. public synchronized void setReuseAddress(boolean on) throws SocketException {
  909. if (isClosed())
  910. throw new SocketException("Socket is closed");
  911. // Integer instead of Boolean for compatibility with older DatagramSocketImpl
  912. if (oldImpl)
  913. getImpl().setOption(SocketOptions.SO_REUSEADDR, new Integer(on?-1:0));
  914. else
  915. getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
  916. }
  917. /**
  918. * Tests if SO_REUSEADDR is enabled.
  919. *
  920. * @return a <code>boolean</code> indicating whether or not SO_REUSEADDR is enabled.
  921. * @exception SocketException if there is an error
  922. * in the underlying protocol, such as an UDP error.
  923. * @since 1.4
  924. * @see #setReuseAddress(boolean)
  925. */
  926. public synchronized boolean getReuseAddress() throws SocketException {
  927. if (isClosed())
  928. throw new SocketException("Socket is closed");
  929. Object o = getImpl().getOption(SocketOptions.SO_REUSEADDR);
  930. return ((Boolean)o).booleanValue();
  931. }
  932. /**
  933. * Enable/disable SO_BROADCAST.
  934. * @param on whether or not to have broadcast turned on.
  935. * @exception SocketException if there is an error
  936. * in the underlying protocol, such as an UDP error.
  937. * @since 1.4
  938. * @see #getBroadcast()
  939. */
  940. public synchronized void setBroadcast(boolean on) throws SocketException {
  941. if (isClosed())
  942. throw new SocketException("Socket is closed");
  943. getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(on));
  944. }
  945. /**
  946. * Tests if SO_BROADCAST is enabled.
  947. * @return a <code>boolean</code> indicating whether or not SO_BROADCAST is enabled.
  948. * @exception SocketException if there is an error
  949. * in the underlying protocol, such as an UDP error.
  950. * @since 1.4
  951. * @see #setBroadcast(boolean)
  952. */
  953. public synchronized boolean getBroadcast() throws SocketException {
  954. if (isClosed())
  955. throw new SocketException("Socket is closed");
  956. return ((Boolean)(getImpl().getOption(SocketOptions.SO_BROADCAST))).booleanValue();
  957. }
  958. /**
  959. * Sets traffic class or type-of-service octet in the IP
  960. * datagram header for datagrams sent from this DatagramSocket.
  961. * As the underlying network implementation may ignore this
  962. * value applications should consider it a hint.
  963. *
  964. * <P> The tc <B>must</B> be in the range <code> 0 <= tc <=
  965. * 255</code> or an IllegalArgumentException will be thrown.
  966. * <p>Notes:
  967. * <p> for Internet Protocol v4 the value consists of an octet
  968. * with precedence and TOS fields as detailed in RFC 1349. The
  969. * TOS field is bitset created by bitwise-or'ing values such
  970. * the following :-
  971. * <p>
  972. * <UL>
  973. * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
  974. * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
  975. * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
  976. * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
  977. * </UL>
  978. * The last low order bit is always ignored as this
  979. * corresponds to the MBZ (must be zero) bit.
  980. * <p>
  981. * Setting bits in the precedence field may result in a
  982. * SocketException indicating that the operation is not
  983. * permitted.
  984. * <p>
  985. * for Internet Protocol v6 <code>tc</code> is the value that
  986. * would be placed into the sin6_flowinfo field of the IP header.
  987. *
  988. * @param tc an <code>int</code> value for the bitset.
  989. * @throws SocketException if there is an error setting the
  990. * traffic class or type-of-service
  991. * @since 1.4
  992. * @see #getTrafficClass
  993. */
  994. public synchronized void setTrafficClass(int tc) throws SocketException {
  995. if (tc < 0 || tc > 255)
  996. throw new IllegalArgumentException("tc is not in range 0 -- 255");
  997. if (isClosed())
  998. throw new SocketException("Socket is closed");
  999. getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
  1000. }
  1001. /**
  1002. * Gets traffic class or type-of-service in the IP datagram
  1003. * header for packets sent from this DatagramSocket.
  1004. * <p>
  1005. * As the underlying network implementation may ignore the
  1006. * traffic class or type-of-service set using {@link #setTrafficClass(int)}
  1007. * this method may return a different value than was previously
  1008. * set using the {@link #setTrafficClass(int)} method on this
  1009. * DatagramSocket.
  1010. *
  1011. * @return the traffic class or type-of-service already set
  1012. * @throws SocketException if there is an error obtaining the
  1013. * traffic class or type-of-service value.
  1014. * @since 1.4
  1015. * @see #setTrafficClass(int)
  1016. */
  1017. public synchronized int getTrafficClass() throws SocketException {
  1018. if (isClosed())
  1019. throw new SocketException("Socket is closed");
  1020. return ((Integer)(getImpl().getOption(SocketOptions.IP_TOS))).intValue();
  1021. }
  1022. /**
  1023. * Closes this datagram socket.
  1024. * <p>
  1025. * Any thread currently blocked in {#link receive} upon this socket
  1026. * will throw a {@link SocketException}.
  1027. *
  1028. * <p> If this socket has an associated channel then the channel is closed
  1029. * as well.
  1030. *
  1031. * @revised 1.4
  1032. * @spec JSR-51
  1033. */
  1034. public void close() {
  1035. synchronized(closeLock) {
  1036. if (isClosed())
  1037. return;
  1038. impl.close();
  1039. closed = true;
  1040. }
  1041. }
  1042. /**
  1043. * Returns whether the socket is closed or not.
  1044. *
  1045. * @return true if the socket has been closed
  1046. * @since 1.4
  1047. */
  1048. public boolean isClosed() {
  1049. synchronized(closeLock) {
  1050. return closed;
  1051. }
  1052. }
  1053. /**
  1054. * Returns the unique {@link java.nio.channels.DatagramChannel} object
  1055. * associated with this datagram socket, if any.
  1056. *
  1057. * <p> A datagram socket will have a channel if, and only if, the channel
  1058. * itself was created via the {@link java.nio.channels.DatagramChannel#open
  1059. * DatagramChannel.open} method.
  1060. *
  1061. * @return the datagram channel associated with this datagram socket,
  1062. * or <tt>null</tt> if this socket was not created for a channel
  1063. *
  1064. * @since 1.4
  1065. * @spec JSR-51
  1066. */
  1067. public DatagramChannel getChannel() {
  1068. return null;
  1069. }
  1070. /**
  1071. * The factory for all datagram sockets.
  1072. */
  1073. static DatagramSocketImplFactory factory;
  1074. /**
  1075. * Sets the datagram socket implementation factory for the
  1076. * application. The factory can be specified only once.
  1077. * <p>
  1078. * When an application creates a new datagram socket, the socket
  1079. * implementation factory's <code>createDatagramSocketImpl</code> method is
  1080. * called to create the actual datagram socket implementation.
  1081. * <p>
  1082. * Passing <code>null</code> to the method is a no-op unless the factory
  1083. * was already set.
  1084. *
  1085. * <p>If there is a security manager, this method first calls
  1086. * the security manager's <code>checkSetFactory</code> method
  1087. * to ensure the operation is allowed.
  1088. * This could result in a SecurityException.
  1089. *
  1090. * @param fac the desired factory.
  1091. * @exception IOException if an I/O error occurs when setting the
  1092. * datagram socket factory.
  1093. * @exception SocketException if the factory is already defined.
  1094. * @exception SecurityException if a security manager exists and its
  1095. * <code>checkSetFactory</code> method doesn't allow the
  1096. operation.
  1097. * @see
  1098. java.net.DatagramSocketImplFactory#createDatagramSocketImpl()
  1099. * @see SecurityManager#checkSetFactory
  1100. */
  1101. public static synchronized void
  1102. setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
  1103. throws IOException
  1104. {
  1105. if (factory != null) {
  1106. throw new SocketException("factory already defined");
  1107. }
  1108. SecurityManager security = System.getSecurityManager();
  1109. if (security != null) {
  1110. security.checkSetFactory();
  1111. }
  1112. factory = fac;
  1113. }
  1114. }