blob: bb4760f1184ac478bf865bf325b119f6814b7626 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07002 * Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved.
J. Duke319a3b92007-12-01 00:00:00 +00003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07007 * published by the Free Software Foundation. Oracle designates this
J. Duke319a3b92007-12-01 00:00:00 +00008 * particular file as subject to the "Classpath" exception as provided
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07009 * by Oracle in the LICENSE file that accompanied this code.
J. Duke319a3b92007-12-01 00:00:00 +000010 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
Kelly O'Hairfe008ae2010-05-25 15:58:33 -070021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
J. Duke319a3b92007-12-01 00:00:00 +000024 */
25
26package java.net;
27
28import java.io.IOException;
29import java.io.InterruptedIOException;
30import java.util.Enumeration;
31
32/**
33 * The multicast datagram socket class is useful for sending
34 * and receiving IP multicast packets. A MulticastSocket is
35 * a (UDP) DatagramSocket, with additional capabilities for
36 * joining "groups" of other multicast hosts on the internet.
37 * <P>
38 * A multicast group is specified by a class D IP address
39 * and by a standard UDP port number. Class D IP addresses
40 * are in the range <CODE>224.0.0.0</CODE> to <CODE>239.255.255.255</CODE>,
41 * inclusive. The address 224.0.0.0 is reserved and should not be used.
42 * <P>
43 * One would join a multicast group by first creating a MulticastSocket
44 * with the desired port, then invoking the
45 * <CODE>joinGroup(InetAddress groupAddr)</CODE>
46 * method:
47 * <PRE>
48 * // join a Multicast group and send the group salutations
49 * ...
50 * String msg = "Hello";
51 * InetAddress group = InetAddress.getByName("228.5.6.7");
52 * MulticastSocket s = new MulticastSocket(6789);
53 * s.joinGroup(group);
54 * DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),
55 * group, 6789);
56 * s.send(hi);
57 * // get their responses!
58 * byte[] buf = new byte[1000];
59 * DatagramPacket recv = new DatagramPacket(buf, buf.length);
60 * s.receive(recv);
61 * ...
62 * // OK, I'm done talking - leave the group...
63 * s.leaveGroup(group);
64 * </PRE>
65 *
66 * When one sends a message to a multicast group, <B>all</B> subscribing
67 * recipients to that host and port receive the message (within the
68 * time-to-live range of the packet, see below). The socket needn't
69 * be a member of the multicast group to send messages to it.
70 * <P>
71 * When a socket subscribes to a multicast group/port, it receives
72 * datagrams sent by other hosts to the group/port, as do all other
73 * members of the group and port. A socket relinquishes membership
74 * in a group by the leaveGroup(InetAddress addr) method. <B>
75 * Multiple MulticastSocket's</B> may subscribe to a multicast group
76 * and port concurrently, and they will all receive group datagrams.
77 * <P>
78 * Currently applets are not allowed to use multicast sockets.
79 *
80 * @author Pavani Diwanji
81 * @since JDK1.1
82 */
83public
84class MulticastSocket extends DatagramSocket {
85 /**
86 * Create a multicast socket.
87 *
88 * <p>If there is a security manager,
89 * its <code>checkListen</code> method is first called
90 * with 0 as its argument to ensure the operation is allowed.
91 * This could result in a SecurityException.
92 * <p>
93 * When the socket is created the
94 * {@link DatagramSocket#setReuseAddress(boolean)} method is
95 * called to enable the SO_REUSEADDR socket option.
96 *
97 * @exception IOException if an I/O exception occurs
98 * while creating the MulticastSocket
99 * @exception SecurityException if a security manager exists and its
100 * <code>checkListen</code> method doesn't allow the operation.
101 * @see SecurityManager#checkListen
102 * @see java.net.DatagramSocket#setReuseAddress(boolean)
103 */
104 public MulticastSocket() throws IOException {
105 this(new InetSocketAddress(0));
106 }
107
108 /**
109 * Create a multicast socket and bind it to a specific port.
110 *
111 * <p>If there is a security manager,
112 * its <code>checkListen</code> method is first called
113 * with the <code>port</code> argument
114 * as its argument to ensure the operation is allowed.
115 * This could result in a SecurityException.
116 * <p>
117 * When the socket is created the
118 * {@link DatagramSocket#setReuseAddress(boolean)} method is
119 * called to enable the SO_REUSEADDR socket option.
120 *
121 * @param port port to use
122 * @exception IOException if an I/O exception occurs
123 * while creating the MulticastSocket
124 * @exception SecurityException if a security manager exists and its
125 * <code>checkListen</code> method doesn't allow the operation.
126 * @see SecurityManager#checkListen
127 * @see java.net.DatagramSocket#setReuseAddress(boolean)
128 */
129 public MulticastSocket(int port) throws IOException {
130 this(new InetSocketAddress(port));
131 }
132
133 /**
134 * Create a MulticastSocket bound to the specified socket address.
135 * <p>
136 * Or, if the address is <code>null</code>, create an unbound socket.
137 * <p>
138 * <p>If there is a security manager,
139 * its <code>checkListen</code> method is first called
140 * with the SocketAddress port as its argument to ensure the operation is allowed.
141 * This could result in a SecurityException.
142 * <p>
143 * When the socket is created the
144 * {@link DatagramSocket#setReuseAddress(boolean)} method is
145 * called to enable the SO_REUSEADDR socket option.
146 *
147 * @param bindaddr Socket address to bind to, or <code>null</code> for
148 * an unbound socket.
149 * @exception IOException if an I/O exception occurs
150 * while creating the MulticastSocket
151 * @exception SecurityException if a security manager exists and its
152 * <code>checkListen</code> method doesn't allow the operation.
153 * @see SecurityManager#checkListen
154 * @see java.net.DatagramSocket#setReuseAddress(boolean)
155 *
156 * @since 1.4
157 */
158 public MulticastSocket(SocketAddress bindaddr) throws IOException {
159 super((SocketAddress) null);
160
161 // Enable SO_REUSEADDR before binding
162 setReuseAddress(true);
163
164 if (bindaddr != null) {
Michael McMahon518e8462011-09-09 14:04:44 +0100165 try {
166 bind(bindaddr);
167 } finally {
168 if (!isBound())
169 close();
170 }
J. Duke319a3b92007-12-01 00:00:00 +0000171 }
172 }
173
174 /**
175 * The lock on the socket's TTL. This is for set/getTTL and
176 * send(packet,ttl).
177 */
178 private Object ttlLock = new Object();
179
180 /**
181 * The lock on the socket's interface - used by setInterface
182 * and getInterface
183 */
184 private Object infLock = new Object();
185
186 /**
187 * The "last" interface set by setInterface on this MulticastSocket
188 */
189 private InetAddress infAddress = null;
190
191
192 /**
193 * Set the default time-to-live for multicast packets sent out
194 * on this <code>MulticastSocket</code> in order to control the
195 * scope of the multicasts.
196 *
197 * <p>The ttl is an <b>unsigned</b> 8-bit quantity, and so <B>must</B> be
198 * in the range <code> 0 <= ttl <= 0xFF </code>.
199 *
200 * @param ttl the time-to-live
201 * @exception IOException if an I/O exception occurs
202 * while setting the default time-to-live value
203 * @deprecated use the setTimeToLive method instead, which uses
204 * <b>int</b> instead of <b>byte</b> as the type for ttl.
205 * @see #getTTL()
206 */
207 @Deprecated
208 public void setTTL(byte ttl) throws IOException {
209 if (isClosed())
210 throw new SocketException("Socket is closed");
211 getImpl().setTTL(ttl);
212 }
213
214 /**
215 * Set the default time-to-live for multicast packets sent out
216 * on this {@code MulticastSocket} in order to control the
217 * scope of the multicasts.
218 *
219 * <P> The ttl <B>must</B> be in the range {@code 0 <= ttl <=
220 * 255} or an {@code IllegalArgumentException} will be thrown.
221 * Multicast packets sent with a TTL of {@code 0} are not transmitted
222 * on the network but may be delivered locally.
223 *
224 * @param ttl
225 * the time-to-live
226 *
227 * @throws IOException
228 * if an I/O exception occurs while setting the
229 * default time-to-live value
230 *
231 * @see #getTimeToLive()
232 */
233 public void setTimeToLive(int ttl) throws IOException {
234 if (ttl < 0 || ttl > 255) {
235 throw new IllegalArgumentException("ttl out of range");
236 }
237 if (isClosed())
238 throw new SocketException("Socket is closed");
239 getImpl().setTimeToLive(ttl);
240 }
241
242 /**
243 * Get the default time-to-live for multicast packets sent out on
244 * the socket.
245 *
246 * @exception IOException if an I/O exception occurs
247 * while getting the default time-to-live value
248 * @return the default time-to-live value
249 * @deprecated use the getTimeToLive method instead, which returns
250 * an <b>int</b> instead of a <b>byte</b>.
251 * @see #setTTL(byte)
252 */
253 @Deprecated
254 public byte getTTL() throws IOException {
255 if (isClosed())
256 throw new SocketException("Socket is closed");
257 return getImpl().getTTL();
258 }
259
260 /**
261 * Get the default time-to-live for multicast packets sent out on
262 * the socket.
263 * @exception IOException if an I/O exception occurs while
264 * getting the default time-to-live value
265 * @return the default time-to-live value
266 * @see #setTimeToLive(int)
267 */
268 public int getTimeToLive() throws IOException {
269 if (isClosed())
270 throw new SocketException("Socket is closed");
271 return getImpl().getTimeToLive();
272 }
273
274 /**
275 * Joins a multicast group. Its behavior may be affected by
276 * <code>setInterface</code> or <code>setNetworkInterface</code>.
277 *
278 * <p>If there is a security manager, this method first
279 * calls its <code>checkMulticast</code> method
280 * with the <code>mcastaddr</code> argument
281 * as its argument.
282 *
283 * @param mcastaddr is the multicast address to join
284 *
285 * @exception IOException if there is an error joining
286 * or when the address is not a multicast address.
287 * @exception SecurityException if a security manager exists and its
288 * <code>checkMulticast</code> method doesn't allow the join.
289 *
290 * @see SecurityManager#checkMulticast(InetAddress)
291 */
292 public void joinGroup(InetAddress mcastaddr) throws IOException {
293 if (isClosed()) {
294 throw new SocketException("Socket is closed");
295 }
296
Michael McMahond7402c72009-12-02 12:17:42 +0000297 checkAddress(mcastaddr, "joinGroup");
J. Duke319a3b92007-12-01 00:00:00 +0000298 SecurityManager security = System.getSecurityManager();
299 if (security != null) {
300 security.checkMulticast(mcastaddr);
301 }
302
303 if (!mcastaddr.isMulticastAddress()) {
304 throw new SocketException("Not a multicast address");
305 }
306
307 getImpl().join(mcastaddr);
308 }
309
310 /**
311 * Leave a multicast group. Its behavior may be affected by
312 * <code>setInterface</code> or <code>setNetworkInterface</code>.
313 *
314 * <p>If there is a security manager, this method first
315 * calls its <code>checkMulticast</code> method
316 * with the <code>mcastaddr</code> argument
317 * as its argument.
318 *
319 * @param mcastaddr is the multicast address to leave
320 * @exception IOException if there is an error leaving
321 * or when the address is not a multicast address.
322 * @exception SecurityException if a security manager exists and its
323 * <code>checkMulticast</code> method doesn't allow the operation.
324 *
325 * @see SecurityManager#checkMulticast(InetAddress)
326 */
327 public void leaveGroup(InetAddress mcastaddr) throws IOException {
328 if (isClosed()) {
329 throw new SocketException("Socket is closed");
330 }
331
Michael McMahond7402c72009-12-02 12:17:42 +0000332 checkAddress(mcastaddr, "leaveGroup");
J. Duke319a3b92007-12-01 00:00:00 +0000333 SecurityManager security = System.getSecurityManager();
334 if (security != null) {
335 security.checkMulticast(mcastaddr);
336 }
337
338 if (!mcastaddr.isMulticastAddress()) {
339 throw new SocketException("Not a multicast address");
340 }
341
342 getImpl().leave(mcastaddr);
343 }
344
345 /**
346 * Joins the specified multicast group at the specified interface.
347 *
348 * <p>If there is a security manager, this method first
349 * calls its <code>checkMulticast</code> method
350 * with the <code>mcastaddr</code> argument
351 * as its argument.
352 *
353 * @param mcastaddr is the multicast address to join
354 * @param netIf specifies the local interface to receive multicast
355 * datagram packets, or <i>null</i> to defer to the interface set by
356 * {@link MulticastSocket#setInterface(InetAddress)} or
357 * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
358 *
359 * @exception IOException if there is an error joining
360 * or when the address is not a multicast address.
361 * @exception SecurityException if a security manager exists and its
362 * <code>checkMulticast</code> method doesn't allow the join.
363 * @throws IllegalArgumentException if mcastaddr is null or is a
364 * SocketAddress subclass not supported by this socket
365 *
366 * @see SecurityManager#checkMulticast(InetAddress)
367 * @since 1.4
368 */
369 public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
370 throws IOException {
371 if (isClosed())
372 throw new SocketException("Socket is closed");
373
374 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
375 throw new IllegalArgumentException("Unsupported address type");
376
377 if (oldImpl)
378 throw new UnsupportedOperationException();
379
Michael McMahond7402c72009-12-02 12:17:42 +0000380 checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "joinGroup");
J. Duke319a3b92007-12-01 00:00:00 +0000381 SecurityManager security = System.getSecurityManager();
382 if (security != null) {
383 security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress());
384 }
385
386 if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) {
387 throw new SocketException("Not a multicast address");
388 }
389
390 getImpl().joinGroup(mcastaddr, netIf);
391 }
392
393 /**
394 * Leave a multicast group on a specified local interface.
395 *
396 * <p>If there is a security manager, this method first
397 * calls its <code>checkMulticast</code> method
398 * with the <code>mcastaddr</code> argument
399 * as its argument.
400 *
401 * @param mcastaddr is the multicast address to leave
402 * @param netIf specifies the local interface or <i>null</i> to defer
403 * to the interface set by
404 * {@link MulticastSocket#setInterface(InetAddress)} or
405 * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
406 * @exception IOException if there is an error leaving
407 * or when the address is not a multicast address.
408 * @exception SecurityException if a security manager exists and its
409 * <code>checkMulticast</code> method doesn't allow the operation.
410 * @throws IllegalArgumentException if mcastaddr is null or is a
411 * SocketAddress subclass not supported by this socket
412 *
413 * @see SecurityManager#checkMulticast(InetAddress)
414 * @since 1.4
415 */
416 public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
417 throws IOException {
418 if (isClosed())
419 throw new SocketException("Socket is closed");
420
421 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
422 throw new IllegalArgumentException("Unsupported address type");
423
424 if (oldImpl)
425 throw new UnsupportedOperationException();
426
Michael McMahond7402c72009-12-02 12:17:42 +0000427 checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "leaveGroup");
J. Duke319a3b92007-12-01 00:00:00 +0000428 SecurityManager security = System.getSecurityManager();
429 if (security != null) {
430 security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress());
431 }
432
433 if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) {
434 throw new SocketException("Not a multicast address");
435 }
436
437 getImpl().leaveGroup(mcastaddr, netIf);
438 }
439
440 /**
441 * Set the multicast network interface used by methods
442 * whose behavior would be affected by the value of the
443 * network interface. Useful for multihomed hosts.
444 * @param inf the InetAddress
445 * @exception SocketException if there is an error in
446 * the underlying protocol, such as a TCP error.
447 * @see #getInterface()
448 */
449 public void setInterface(InetAddress inf) throws SocketException {
450 if (isClosed()) {
451 throw new SocketException("Socket is closed");
452 }
Michael McMahond7402c72009-12-02 12:17:42 +0000453 checkAddress(inf, "setInterface");
J. Duke319a3b92007-12-01 00:00:00 +0000454 synchronized (infLock) {
455 getImpl().setOption(SocketOptions.IP_MULTICAST_IF, inf);
456 infAddress = inf;
457 }
458 }
459
460 /**
461 * Retrieve the address of the network interface used for
462 * multicast packets.
463 *
464 * @return An <code>InetAddress</code> representing
465 * the address of the network interface used for
466 * multicast packets.
467 *
468 * @exception SocketException if there is an error in
469 * the underlying protocol, such as a TCP error.
470 *
471 * @see #setInterface(java.net.InetAddress)
472 */
473 public InetAddress getInterface() throws SocketException {
474 if (isClosed()) {
475 throw new SocketException("Socket is closed");
476 }
477 synchronized (infLock) {
478 InetAddress ia =
479 (InetAddress)getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
480
481 /**
482 * No previous setInterface or interface can be
483 * set using setNetworkInterface
484 */
485 if (infAddress == null) {
486 return ia;
487 }
488
489 /**
490 * Same interface set with setInterface?
491 */
492 if (ia.equals(infAddress)) {
493 return ia;
494 }
495
496 /**
497 * Different InetAddress from what we set with setInterface
498 * so enumerate the current interface to see if the
499 * address set by setInterface is bound to this interface.
500 */
501 try {
502 NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
503 Enumeration addrs = ni.getInetAddresses();
504 while (addrs.hasMoreElements()) {
505 InetAddress addr = (InetAddress)(addrs.nextElement());
506 if (addr.equals(infAddress)) {
507 return infAddress;
508 }
509 }
510
511 /**
512 * No match so reset infAddress to indicate that the
513 * interface has changed via means
514 */
515 infAddress = null;
516 return ia;
517 } catch (Exception e) {
518 return ia;
519 }
520 }
521 }
522
523 /**
524 * Specify the network interface for outgoing multicast datagrams
525 * sent on this socket.
526 *
527 * @param netIf the interface
528 * @exception SocketException if there is an error in
529 * the underlying protocol, such as a TCP error.
530 * @see #getNetworkInterface()
531 * @since 1.4
532 */
533 public void setNetworkInterface(NetworkInterface netIf)
534 throws SocketException {
535
536 synchronized (infLock) {
537 getImpl().setOption(SocketOptions.IP_MULTICAST_IF2, netIf);
538 infAddress = null;
539 }
540 }
541
542 /**
543 * Get the multicast network interface set.
544 *
545 * @exception SocketException if there is an error in
546 * the underlying protocol, such as a TCP error.
547 * @return the multicast <code>NetworkInterface</code> currently set
548 * @see #setNetworkInterface(NetworkInterface)
549 * @since 1.4
550 */
551 public NetworkInterface getNetworkInterface() throws SocketException {
552 NetworkInterface ni
553 = (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
554 if (ni.getIndex() == 0) {
555 InetAddress[] addrs = new InetAddress[1];
556 addrs[0] = InetAddress.anyLocalAddress();
557 return new NetworkInterface(addrs[0].getHostName(), 0, addrs);
558 } else {
559 return ni;
560 }
561 }
562
563 /**
564 * Disable/Enable local loopback of multicast datagrams
565 * The option is used by the platform's networking code as a hint
566 * for setting whether multicast data will be looped back to
567 * the local socket.
568 *
569 * <p>Because this option is a hint, applications that want to
570 * verify what loopback mode is set to should call
571 * {@link #getLoopbackMode()}
572 * @param disable <code>true</code> to disable the LoopbackMode
573 * @throws SocketException if an error occurs while setting the value
574 * @since 1.4
575 * @see #getLoopbackMode
576 */
577 public void setLoopbackMode(boolean disable) throws SocketException {
578 getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable));
579 }
580
581 /**
582 * Get the setting for local loopback of multicast datagrams.
583 *
584 * @throws SocketException if an error occurs while getting the value
585 * @return true if the LoopbackMode has been disabled
586 * @since 1.4
587 * @see #setLoopbackMode
588 */
589 public boolean getLoopbackMode() throws SocketException {
590 return ((Boolean)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue();
591 }
592
593 /**
594 * Sends a datagram packet to the destination, with a TTL (time-
595 * to-live) other than the default for the socket. This method
596 * need only be used in instances where a particular TTL is desired;
597 * otherwise it is preferable to set a TTL once on the socket, and
598 * use that default TTL for all packets. This method does <B>not
599 * </B> alter the default TTL for the socket. Its behavior may be
600 * affected by <code>setInterface</code>.
601 *
602 * <p>If there is a security manager, this method first performs some
603 * security checks. First, if <code>p.getAddress().isMulticastAddress()</code>
604 * is true, this method calls the
605 * security manager's <code>checkMulticast</code> method
606 * with <code>p.getAddress()</code> and <code>ttl</code> as its arguments.
607 * If the evaluation of that expression is false,
608 * this method instead calls the security manager's
609 * <code>checkConnect</code> method with arguments
610 * <code>p.getAddress().getHostAddress()</code> and
611 * <code>p.getPort()</code>. Each call to a security manager method
612 * could result in a SecurityException if the operation is not allowed.
613 *
614 * @param p is the packet to be sent. The packet should contain
615 * the destination multicast ip address and the data to be sent.
616 * One does not need to be the member of the group to send
617 * packets to a destination multicast address.
618 * @param ttl optional time to live for multicast packet.
619 * default ttl is 1.
620 *
621 * @exception IOException is raised if an error occurs i.e
622 * error while setting ttl.
623 * @exception SecurityException if a security manager exists and its
624 * <code>checkMulticast</code> or <code>checkConnect</code>
625 * method doesn't allow the send.
626 *
627 * @deprecated Use the following code or its equivalent instead:
628 * ......
629 * int ttl = mcastSocket.getTimeToLive();
630 * mcastSocket.setTimeToLive(newttl);
631 * mcastSocket.send(p);
632 * mcastSocket.setTimeToLive(ttl);
633 * ......
634 *
635 * @see DatagramSocket#send
636 * @see DatagramSocket#receive
637 * @see SecurityManager#checkMulticast(java.net.InetAddress, byte)
638 * @see SecurityManager#checkConnect
639 */
640 @Deprecated
641 public void send(DatagramPacket p, byte ttl)
642 throws IOException {
643 if (isClosed())
644 throw new SocketException("Socket is closed");
Michael McMahond7402c72009-12-02 12:17:42 +0000645 checkAddress(p.getAddress(), "send");
J. Duke319a3b92007-12-01 00:00:00 +0000646 synchronized(ttlLock) {
647 synchronized(p) {
648 if (connectState == ST_NOT_CONNECTED) {
649 // Security manager makes sure that the multicast address
650 // is allowed one and that the ttl used is less
651 // than the allowed maxttl.
652 SecurityManager security = System.getSecurityManager();
653 if (security != null) {
654 if (p.getAddress().isMulticastAddress()) {
655 security.checkMulticast(p.getAddress(), ttl);
656 } else {
657 security.checkConnect(p.getAddress().getHostAddress(),
658 p.getPort());
659 }
660 }
661 } else {
662 // we're connected
663 InetAddress packetAddress = null;
664 packetAddress = p.getAddress();
665 if (packetAddress == null) {
666 p.setAddress(connectedAddress);
667 p.setPort(connectedPort);
668 } else if ((!packetAddress.equals(connectedAddress)) ||
669 p.getPort() != connectedPort) {
670 throw new SecurityException("connected address and packet address" +
671 " differ");
672 }
673 }
674 byte dttl = getTTL();
675 try {
676 if (ttl != dttl) {
677 // set the ttl
678 getImpl().setTTL(ttl);
679 }
680 // call the datagram method to send
681 getImpl().send(p);
682 } finally {
683 // set it back to default
684 if (ttl != dttl) {
685 getImpl().setTTL(dttl);
686 }
687 }
688 } // synch p
689 } //synch ttl
690 } //method
691}