MulticastSocket.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /* MulticastSocket.java -- Class for using multicast sockets
  2. Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2007
  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. package java.net;
  33. import java.io.IOException;
  34. import java.util.Enumeration;
  35. /**
  36. * Written using on-line Java Platform 1.2 API Specification, as well
  37. * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
  38. * Status: Believed complete and correct.
  39. */
  40. /**
  41. * This class models a multicast UDP socket. A multicast address is a
  42. * class D internet address (one whose most significant bits are 1110).
  43. * A multicast group consists of a multicast address and a well known
  44. * port number. All members of the group listening on that address and
  45. * port will receive all the broadcasts to the group.
  46. * <p>
  47. * Please note that applets are not allowed to use multicast sockets
  48. *
  49. * Written using on-line Java Platform 1.2 API Specification, as well
  50. * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
  51. * Status: Believed complete and correct.
  52. *
  53. * @author Warren Levy (warrenl@cygnus.com)
  54. * @author Aaron M. Renn (arenn@urbanophile.com) (Documentation comments)
  55. * @since 1.1
  56. * @date May 18, 1999.
  57. */
  58. public class MulticastSocket extends DatagramSocket
  59. {
  60. /**
  61. * Create a MulticastSocket that this not bound to any address
  62. *
  63. * @exception IOException If an error occurs
  64. * @exception SecurityException If a security manager exists and its
  65. * checkListen method doesn't allow the operation
  66. */
  67. public MulticastSocket() throws IOException
  68. {
  69. this(new InetSocketAddress(0));
  70. }
  71. /**
  72. * Create a multicast socket bound to the specified port
  73. *
  74. * @param port The port to bind to
  75. *
  76. * @exception IOException If an error occurs
  77. * @exception SecurityException If a security manager exists and its
  78. * checkListen method doesn't allow the operation
  79. */
  80. public MulticastSocket(int port) throws IOException
  81. {
  82. this(new InetSocketAddress(port));
  83. }
  84. /**
  85. * Create a multicast socket bound to the specified SocketAddress.
  86. *
  87. * @param address The SocketAddress the multicast socket will be bound to
  88. *
  89. * @exception IOException If an error occurs
  90. * @exception SecurityException If a security manager exists and its
  91. * checkListen method doesn't allow the operation
  92. *
  93. * @since 1.4
  94. */
  95. public MulticastSocket(SocketAddress address) throws IOException
  96. {
  97. super((SocketAddress) null);
  98. setReuseAddress(true);
  99. if (address != null)
  100. bind(address);
  101. }
  102. /**
  103. * Returns the interface being used for multicast packets
  104. *
  105. * @return The multicast interface
  106. *
  107. * @exception SocketException If an error occurs
  108. */
  109. public InetAddress getInterface() throws SocketException
  110. {
  111. if (isClosed())
  112. throw new SocketException("socket is closed");
  113. return (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
  114. }
  115. /**
  116. * Returns the current value of the "Time to Live" option. This is the
  117. * number of hops a packet can make before it "expires". This method id
  118. * deprecated. Use <code>getTimeToLive</code> instead.
  119. *
  120. * @return The TTL value
  121. *
  122. * @exception IOException If an error occurs
  123. *
  124. * @deprecated 1.2 Replaced by getTimeToLive()
  125. *
  126. * @see MulticastSocket#getTimeToLive()
  127. */
  128. public byte getTTL() throws IOException
  129. {
  130. if (isClosed())
  131. throw new SocketException("socket is closed");
  132. // Use getTTL here rather than getTimeToLive in case we're using an impl
  133. // other than the default PlainDatagramSocketImpl and it doesn't have
  134. // getTimeToLive yet.
  135. return getImpl().getTTL();
  136. }
  137. /**
  138. * Returns the current value of the "Time to Live" option. This is the
  139. * number of hops a packet can make before it "expires".
  140. *
  141. * @return The TTL value
  142. *
  143. * @exception IOException If an error occurs
  144. *
  145. * @since 1.2
  146. */
  147. public int getTimeToLive() throws IOException
  148. {
  149. if (isClosed())
  150. throw new SocketException("socket is closed");
  151. return getImpl().getTimeToLive();
  152. }
  153. /**
  154. * Sets the interface to use for sending multicast packets.
  155. *
  156. * @param addr The new interface to use.
  157. *
  158. * @exception SocketException If an error occurs.
  159. *
  160. * @since 1.4
  161. */
  162. public void setInterface(InetAddress addr) throws SocketException
  163. {
  164. if (isClosed())
  165. throw new SocketException("socket is closed");
  166. getImpl().setOption(SocketOptions.IP_MULTICAST_IF, addr);
  167. }
  168. /**
  169. * Sets the local network interface used to send multicast messages
  170. *
  171. * @param netIf The local network interface used to send multicast messages
  172. *
  173. * @exception SocketException If an error occurs
  174. *
  175. * @see MulticastSocket#getNetworkInterface()
  176. *
  177. * @since 1.4
  178. */
  179. public void setNetworkInterface(NetworkInterface netIf)
  180. throws SocketException
  181. {
  182. if (isClosed())
  183. throw new SocketException("socket is closed");
  184. InetAddress address;
  185. if (netIf != null)
  186. out:
  187. {
  188. Enumeration e = netIf.getInetAddresses();
  189. if (getLocalAddress() instanceof Inet4Address)
  190. {
  191. // Search for a IPv4 address.
  192. while (e.hasMoreElements())
  193. {
  194. address = (InetAddress) e.nextElement();
  195. if (address instanceof Inet4Address)
  196. break out;
  197. }
  198. throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
  199. }
  200. else if (getLocalAddress() instanceof Inet6Address)
  201. {
  202. // Search for a IPv6 address.
  203. while (e.hasMoreElements())
  204. {
  205. address = (InetAddress) e.nextElement();
  206. if (address instanceof Inet6Address)
  207. break out;
  208. }
  209. throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
  210. }
  211. else
  212. throw new SocketException("interface " + netIf.getName() + " has no suitable IP address");
  213. }
  214. else
  215. address = InetAddress.ANY_IF;
  216. getImpl().setOption(SocketOptions.IP_MULTICAST_IF, address);
  217. }
  218. /**
  219. * Gets the local network interface which is used to send multicast messages
  220. *
  221. * @return The local network interface to send multicast messages
  222. *
  223. * @exception SocketException If an error occurs
  224. *
  225. * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
  226. *
  227. * @since 1.4
  228. */
  229. public NetworkInterface getNetworkInterface() throws SocketException
  230. {
  231. if (isClosed())
  232. throw new SocketException("socket is closed");
  233. InetAddress address =
  234. (InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
  235. // FIXME: libgcj doesn't have createAnyInterface.
  236. // if (address.isAnyLocalAddress())
  237. // return NetworkInterface.createAnyInterface();
  238. NetworkInterface netIf = NetworkInterface.getByInetAddress(address);
  239. return netIf;
  240. }
  241. /**
  242. * Disable/Enable local loopback of multicast packets. The option is used by
  243. * the platform's networking code as a hint for setting whether multicast
  244. * data will be looped back to the local socket.
  245. *
  246. * Because this option is a hint, applications that want to verify what
  247. * loopback mode is set to should call #getLoopbackMode
  248. *
  249. * @param disable True to disable loopback mode
  250. *
  251. * @exception SocketException If an error occurs
  252. *
  253. * @since 1.4
  254. */
  255. public void setLoopbackMode(boolean disable) throws SocketException
  256. {
  257. if (isClosed())
  258. throw new SocketException("socket is closed");
  259. getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP,
  260. Boolean.valueOf(disable));
  261. }
  262. /**
  263. * Checks if local loopback mode is enabled
  264. *
  265. * @return true if loopback mode is enabled, false otherwise
  266. *
  267. * @exception SocketException If an error occurs
  268. *
  269. * @since 1.4
  270. */
  271. public boolean getLoopbackMode() throws SocketException
  272. {
  273. if (isClosed())
  274. throw new SocketException("socket is closed");
  275. Object buf = getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP);
  276. if (buf instanceof Boolean)
  277. return ((Boolean) buf).booleanValue();
  278. throw new SocketException("unexpected type");
  279. }
  280. /**
  281. * Sets the "Time to Live" value for a socket. The value must be between
  282. * 1 and 255.
  283. *
  284. * @param ttl The new TTL value
  285. *
  286. * @exception IOException If an error occurs
  287. *
  288. * @deprecated 1.2 Replaced by <code>setTimeToLive</code>
  289. *
  290. * @see MulticastSocket#setTimeToLive(int ttl)
  291. */
  292. public void setTTL(byte ttl) throws IOException
  293. {
  294. if (isClosed())
  295. throw new SocketException("socket is closed");
  296. // Use setTTL here rather than setTimeToLive in case we're using an impl
  297. // other than the default PlainDatagramSocketImpl and it doesn't have
  298. // setTimeToLive yet.
  299. getImpl().setTTL(ttl);
  300. }
  301. /**
  302. * Sets the "Time to Live" value for a socket. The value must be between
  303. * 0 and 255, inclusive.
  304. *
  305. * @param ttl The new TTL value
  306. *
  307. * @exception IOException If an error occurs
  308. *
  309. * @since 1.2
  310. */
  311. public void setTimeToLive(int ttl) throws IOException
  312. {
  313. if (isClosed())
  314. throw new SocketException("socket is closed");
  315. if (ttl < 0 || ttl > 255)
  316. throw new IllegalArgumentException("Invalid ttl: " + ttl);
  317. getImpl().setTimeToLive(ttl);
  318. }
  319. /**
  320. * Joins the specified multicast group.
  321. *
  322. * @param mcastaddr The address of the group to join
  323. *
  324. * @exception IOException If an error occurs
  325. * @exception SecurityException If a security manager exists and its
  326. * checkMulticast method doesn't allow the operation
  327. */
  328. public void joinGroup(InetAddress mcastaddr) throws IOException
  329. {
  330. if (isClosed())
  331. throw new SocketException("socket is closed");
  332. if (! mcastaddr.isMulticastAddress())
  333. throw new IOException("Not a Multicast address");
  334. SecurityManager s = System.getSecurityManager();
  335. if (s != null)
  336. s.checkMulticast(mcastaddr);
  337. getImpl().join(mcastaddr);
  338. }
  339. /**
  340. * Leaves the specified multicast group
  341. *
  342. * @param mcastaddr The address of the group to leave
  343. *
  344. * @exception IOException If an error occurs
  345. * @exception SecurityException If a security manager exists and its
  346. * checkMulticast method doesn't allow the operation
  347. */
  348. public void leaveGroup(InetAddress mcastaddr) throws IOException
  349. {
  350. if (isClosed())
  351. throw new SocketException("socket is closed");
  352. if (! mcastaddr.isMulticastAddress())
  353. throw new IOException("Not a Multicast address");
  354. SecurityManager s = System.getSecurityManager();
  355. if (s != null)
  356. s.checkMulticast(mcastaddr);
  357. getImpl().leave(mcastaddr);
  358. }
  359. /**
  360. * Joins the specified mulitcast group on a specified interface.
  361. *
  362. * @param mcastaddr The multicast address to join
  363. * @param netIf The local network interface to receive the multicast
  364. * messages on or null to defer the interface set by #setInterface or
  365. * #setNetworkInterface
  366. *
  367. * @exception IOException If an error occurs
  368. * @exception IllegalArgumentException If address type is not supported
  369. * @exception SecurityException If a security manager exists and its
  370. * checkMulticast method doesn't allow the operation
  371. *
  372. * @see MulticastSocket#setInterface(InetAddress addr)
  373. * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
  374. *
  375. * @since 1.4
  376. */
  377. public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
  378. throws IOException
  379. {
  380. if (isClosed())
  381. throw new SocketException("socket is closed");
  382. if (! (mcastaddr instanceof InetSocketAddress))
  383. throw new IllegalArgumentException("SocketAddress type not supported");
  384. InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
  385. if (! tmp.getAddress().isMulticastAddress())
  386. throw new IOException("Not a Multicast address");
  387. SecurityManager s = System.getSecurityManager();
  388. if (s != null)
  389. s.checkMulticast(tmp.getAddress());
  390. getImpl().joinGroup(mcastaddr, netIf);
  391. }
  392. /**
  393. * Leaves the specified mulitcast group on a specified interface.
  394. *
  395. * @param mcastaddr The multicast address to leave
  396. * @param netIf The local networki interface or null to defer to the
  397. * interface set by setInterface or setNetworkInterface
  398. *
  399. * @exception IOException If an error occurs
  400. * @exception IllegalArgumentException If address type is not supported
  401. * @exception SecurityException If a security manager exists and its
  402. * checkMulticast method doesn't allow the operation
  403. *
  404. * @see MulticastSocket#setInterface(InetAddress addr)
  405. * @see MulticastSocket#setNetworkInterface(NetworkInterface netIf)
  406. *
  407. * @since 1.4
  408. */
  409. public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
  410. throws IOException
  411. {
  412. if (isClosed())
  413. throw new SocketException("socket is closed");
  414. InetSocketAddress tmp = (InetSocketAddress) mcastaddr;
  415. if (! tmp.getAddress().isMulticastAddress())
  416. throw new IOException("Not a Multicast address");
  417. SecurityManager s = System.getSecurityManager();
  418. if (s != null)
  419. s.checkMulticast(tmp.getAddress());
  420. getImpl().leaveGroup(mcastaddr, netIf);
  421. }
  422. /**
  423. * Sends a packet of data to a multicast address with a TTL that is
  424. * different from the default TTL on this socket. The default TTL for
  425. * the socket is not changed.
  426. *
  427. * @param packet The packet of data to send
  428. * @param ttl The TTL for this packet
  429. *
  430. * @exception IOException If an error occurs
  431. * @exception SecurityException If a security manager exists and its
  432. * checkConnect or checkMulticast method doesn't allow the operation
  433. *
  434. * @deprecated
  435. */
  436. public synchronized void send(DatagramPacket packet, byte ttl)
  437. throws IOException
  438. {
  439. if (isClosed())
  440. throw new SocketException("socket is closed");
  441. SecurityManager s = System.getSecurityManager();
  442. if (s != null)
  443. {
  444. InetAddress addr = packet.getAddress();
  445. if (addr.isMulticastAddress())
  446. s.checkPermission(new SocketPermission(addr.getHostName()
  447. + packet.getPort(),
  448. "accept,connect"));
  449. else
  450. s.checkConnect(addr.getHostAddress(), packet.getPort());
  451. }
  452. int oldttl = getImpl().getTimeToLive();
  453. getImpl().setTimeToLive(((int) ttl) & 0xFF);
  454. getImpl().send(packet);
  455. getImpl().setTimeToLive(oldttl);
  456. }
  457. }