History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/net/MulticastSocket.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/net/MulticastSocket.java+686−0
@@ -0,0 +1,686 @@
1/*
2 * Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved.
3 * 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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
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 *
21 * 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.
24 */
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) {
165 bind(bindaddr);
166 }
167 }
168
169 /**
170 * The lock on the socket's TTL. This is for set/getTTL and
171 * send(packet,ttl).
172 */
173 private Object ttlLock = new Object();
174
175 /**
176 * The lock on the socket's interface - used by setInterface
177 * and getInterface
178 */
179 private Object infLock = new Object();
180
181 /**
182 * The "last" interface set by setInterface on this MulticastSocket
183 */
184 private InetAddress infAddress = null;
185
186
187 /**
188 * Set the default time-to-live for multicast packets sent out
189 * on this <code>MulticastSocket</code> in order to control the
190 * scope of the multicasts.
191 *
192 * <p>The ttl is an <b>unsigned</b> 8-bit quantity, and so <B>must</B> be
193 * in the range <code> 0 <= ttl <= 0xFF </code>.
194 *
195 * @param ttl the time-to-live
196 * @exception IOException if an I/O exception occurs
197 * while setting the default time-to-live value
198 * @deprecated use the setTimeToLive method instead, which uses
199 * <b>int</b> instead of <b>byte</b> as the type for ttl.
200 * @see #getTTL()
201 */
202 @Deprecated
203 public void setTTL(byte ttl) throws IOException {
204 if (isClosed())
205 throw new SocketException("Socket is closed");
206 getImpl().setTTL(ttl);
207 }
208
209 /**
210 * Set the default time-to-live for multicast packets sent out
211 * on this {@code MulticastSocket} in order to control the
212 * scope of the multicasts.
213 *
214 * <P> The ttl <B>must</B> be in the range {@code 0 <= ttl <=
215 * 255} or an {@code IllegalArgumentException} will be thrown.
216 * Multicast packets sent with a TTL of {@code 0} are not transmitted
217 * on the network but may be delivered locally.
218 *
219 * @param ttl
220 * the time-to-live
221 *
222 * @throws IOException
223 * if an I/O exception occurs while setting the
224 * default time-to-live value
225 *
226 * @see #getTimeToLive()
227 */
228 public void setTimeToLive(int ttl) throws IOException {
229 if (ttl < 0 || ttl > 255) {
230 throw new IllegalArgumentException("ttl out of range");
231 }
232 if (isClosed())
233 throw new SocketException("Socket is closed");
234 getImpl().setTimeToLive(ttl);
235 }
236
237 /**
238 * Get the default time-to-live for multicast packets sent out on
239 * the socket.
240 *
241 * @exception IOException if an I/O exception occurs
242 * while getting the default time-to-live value
243 * @return the default time-to-live value
244 * @deprecated use the getTimeToLive method instead, which returns
245 * an <b>int</b> instead of a <b>byte</b>.
246 * @see #setTTL(byte)
247 */
248 @Deprecated
249 public byte getTTL() throws IOException {
250 if (isClosed())
251 throw new SocketException("Socket is closed");
252 return getImpl().getTTL();
253 }
254
255 /**
256 * Get the default time-to-live for multicast packets sent out on
257 * the socket.
258 * @exception IOException if an I/O exception occurs while
259 * getting the default time-to-live value
260 * @return the default time-to-live value
261 * @see #setTimeToLive(int)
262 */
263 public int getTimeToLive() throws IOException {
264 if (isClosed())
265 throw new SocketException("Socket is closed");
266 return getImpl().getTimeToLive();
267 }
268
269 /**
270 * Joins a multicast group. Its behavior may be affected by
271 * <code>setInterface</code> or <code>setNetworkInterface</code>.
272 *
273 * <p>If there is a security manager, this method first
274 * calls its <code>checkMulticast</code> method
275 * with the <code>mcastaddr</code> argument
276 * as its argument.
277 *
278 * @param mcastaddr is the multicast address to join
279 *
280 * @exception IOException if there is an error joining
281 * or when the address is not a multicast address.
282 * @exception SecurityException if a security manager exists and its
283 * <code>checkMulticast</code> method doesn't allow the join.
284 *
285 * @see SecurityManager#checkMulticast(InetAddress)
286 */
287 public void joinGroup(InetAddress mcastaddr) throws IOException {
288 if (isClosed()) {
289 throw new SocketException("Socket is closed");
290 }
291
292 checkAddress(mcastaddr, "joinGroup");
293 SecurityManager security = System.getSecurityManager();
294 if (security != null) {
295 security.checkMulticast(mcastaddr);
296 }
297
298 if (!mcastaddr.isMulticastAddress()) {
299 throw new SocketException("Not a multicast address");
300 }
301
302 getImpl().join(mcastaddr);
303 }
304
305 /**
306 * Leave a multicast group. Its behavior may be affected by
307 * <code>setInterface</code> or <code>setNetworkInterface</code>.
308 *
309 * <p>If there is a security manager, this method first
310 * calls its <code>checkMulticast</code> method
311 * with the <code>mcastaddr</code> argument
312 * as its argument.
313 *
314 * @param mcastaddr is the multicast address to leave
315 * @exception IOException if there is an error leaving
316 * or when the address is not a multicast address.
317 * @exception SecurityException if a security manager exists and its
318 * <code>checkMulticast</code> method doesn't allow the operation.
319 *
320 * @see SecurityManager#checkMulticast(InetAddress)
321 */
322 public void leaveGroup(InetAddress mcastaddr) throws IOException {
323 if (isClosed()) {
324 throw new SocketException("Socket is closed");
325 }
326
327 checkAddress(mcastaddr, "leaveGroup");
328 SecurityManager security = System.getSecurityManager();
329 if (security != null) {
330 security.checkMulticast(mcastaddr);
331 }
332
333 if (!mcastaddr.isMulticastAddress()) {
334 throw new SocketException("Not a multicast address");
335 }
336
337 getImpl().leave(mcastaddr);
338 }
339
340 /**
341 * Joins the specified multicast group at the specified interface.
342 *
343 * <p>If there is a security manager, this method first
344 * calls its <code>checkMulticast</code> method
345 * with the <code>mcastaddr</code> argument
346 * as its argument.
347 *
348 * @param mcastaddr is the multicast address to join
349 * @param netIf specifies the local interface to receive multicast
350 * datagram packets, or <i>null</i> to defer to the interface set by
351 * {@link MulticastSocket#setInterface(InetAddress)} or
352 * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
353 *
354 * @exception IOException if there is an error joining
355 * or when the address is not a multicast address.
356 * @exception SecurityException if a security manager exists and its
357 * <code>checkMulticast</code> method doesn't allow the join.
358 * @throws IllegalArgumentException if mcastaddr is null or is a
359 * SocketAddress subclass not supported by this socket
360 *
361 * @see SecurityManager#checkMulticast(InetAddress)
362 * @since 1.4
363 */
364 public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
365 throws IOException {
366 if (isClosed())
367 throw new SocketException("Socket is closed");
368
369 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
370 throw new IllegalArgumentException("Unsupported address type");
371
372 if (oldImpl)
373 throw new UnsupportedOperationException();
374
375 checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "joinGroup");
376 SecurityManager security = System.getSecurityManager();
377 if (security != null) {
378 security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress());
379 }
380
381 if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) {
382 throw new SocketException("Not a multicast address");
383 }
384
385 getImpl().joinGroup(mcastaddr, netIf);
386 }
387
388 /**
389 * Leave a multicast group on a specified local interface.
390 *
391 * <p>If there is a security manager, this method first
392 * calls its <code>checkMulticast</code> method
393 * with the <code>mcastaddr</code> argument
394 * as its argument.
395 *
396 * @param mcastaddr is the multicast address to leave
397 * @param netIf specifies the local interface or <i>null</i> to defer
398 * to the interface set by
399 * {@link MulticastSocket#setInterface(InetAddress)} or
400 * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
401 * @exception IOException if there is an error leaving
402 * or when the address is not a multicast address.
403 * @exception SecurityException if a security manager exists and its
404 * <code>checkMulticast</code> method doesn't allow the operation.
405 * @throws IllegalArgumentException if mcastaddr is null or is a
406 * SocketAddress subclass not supported by this socket
407 *
408 * @see SecurityManager#checkMulticast(InetAddress)
409 * @since 1.4
410 */
411 public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
412 throws IOException {
413 if (isClosed())
414 throw new SocketException("Socket is closed");
415
416 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
417 throw new IllegalArgumentException("Unsupported address type");
418
419 if (oldImpl)
420 throw new UnsupportedOperationException();
421
422 checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "leaveGroup");
423 SecurityManager security = System.getSecurityManager();
424 if (security != null) {
425 security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress());
426 }
427
428 if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) {
429 throw new SocketException("Not a multicast address");
430 }
431
432 getImpl().leaveGroup(mcastaddr, netIf);
433 }
434
435 /**
436 * Set the multicast network interface used by methods
437 * whose behavior would be affected by the value of the
438 * network interface. Useful for multihomed hosts.
439 * @param inf the InetAddress
440 * @exception SocketException if there is an error in
441 * the underlying protocol, such as a TCP error.
442 * @see #getInterface()
443 */
444 public void setInterface(InetAddress inf) throws SocketException {
445 if (isClosed()) {
446 throw new SocketException("Socket is closed");
447 }
448 checkAddress(inf, "setInterface");
449 synchronized (infLock) {
450 getImpl().setOption(SocketOptions.IP_MULTICAST_IF, inf);
451 infAddress = inf;
452 }
453 }
454
455 /**
456 * Retrieve the address of the network interface used for
457 * multicast packets.
458 *
459 * @return An <code>InetAddress</code> representing
460 * the address of the network interface used for
461 * multicast packets.
462 *
463 * @exception SocketException if there is an error in
464 * the underlying protocol, such as a TCP error.
465 *
466 * @see #setInterface(java.net.InetAddress)
467 */
468 public InetAddress getInterface() throws SocketException {
469 if (isClosed()) {
470 throw new SocketException("Socket is closed");
471 }
472 synchronized (infLock) {
473 InetAddress ia =
474 (InetAddress)getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
475
476 /**
477 * No previous setInterface or interface can be
478 * set using setNetworkInterface
479 */
480 if (infAddress == null) {
481 return ia;
482 }
483
484 /**
485 * Same interface set with setInterface?
486 */
487 if (ia.equals(infAddress)) {
488 return ia;
489 }
490
491 /**
492 * Different InetAddress from what we set with setInterface
493 * so enumerate the current interface to see if the
494 * address set by setInterface is bound to this interface.
495 */
496 try {
497 NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
498 Enumeration addrs = ni.getInetAddresses();
499 while (addrs.hasMoreElements()) {
500 InetAddress addr = (InetAddress)(addrs.nextElement());
501 if (addr.equals(infAddress)) {
502 return infAddress;
503 }
504 }
505
506 /**
507 * No match so reset infAddress to indicate that the
508 * interface has changed via means
509 */
510 infAddress = null;
511 return ia;
512 } catch (Exception e) {
513 return ia;
514 }
515 }
516 }
517
518 /**
519 * Specify the network interface for outgoing multicast datagrams
520 * sent on this socket.
521 *
522 * @param netIf the interface
523 * @exception SocketException if there is an error in
524 * the underlying protocol, such as a TCP error.
525 * @see #getNetworkInterface()
526 * @since 1.4
527 */
528 public void setNetworkInterface(NetworkInterface netIf)
529 throws SocketException {
530
531 synchronized (infLock) {
532 getImpl().setOption(SocketOptions.IP_MULTICAST_IF2, netIf);
533 infAddress = null;
534 }
535 }
536
537 /**
538 * Get the multicast network interface set.
539 *
540 * @exception SocketException if there is an error in
541 * the underlying protocol, such as a TCP error.
542 * @return the multicast <code>NetworkInterface</code> currently set
543 * @see #setNetworkInterface(NetworkInterface)
544 * @since 1.4
545 */
546 public NetworkInterface getNetworkInterface() throws SocketException {
547 NetworkInterface ni
548 = (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
549 if (ni.getIndex() == 0) {
550 InetAddress[] addrs = new InetAddress[1];
551 addrs[0] = InetAddress.anyLocalAddress();
552 return new NetworkInterface(addrs[0].getHostName(), 0, addrs);
553 } else {
554 return ni;
555 }
556 }
557
558 /**
559 * Disable/Enable local loopback of multicast datagrams
560 * The option is used by the platform's networking code as a hint
561 * for setting whether multicast data will be looped back to
562 * the local socket.
563 *
564 * <p>Because this option is a hint, applications that want to
565 * verify what loopback mode is set to should call
566 * {@link #getLoopbackMode()}
567 * @param disable <code>true</code> to disable the LoopbackMode
568 * @throws SocketException if an error occurs while setting the value
569 * @since 1.4
570 * @see #getLoopbackMode
571 */
572 public void setLoopbackMode(boolean disable) throws SocketException {
573 getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable));
574 }
575
576 /**
577 * Get the setting for local loopback of multicast datagrams.
578 *
579 * @throws SocketException if an error occurs while getting the value
580 * @return true if the LoopbackMode has been disabled
581 * @since 1.4
582 * @see #setLoopbackMode
583 */
584 public boolean getLoopbackMode() throws SocketException {
585 return ((Boolean)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue();
586 }
587
588 /**
589 * Sends a datagram packet to the destination, with a TTL (time-
590 * to-live) other than the default for the socket. This method
591 * need only be used in instances where a particular TTL is desired;
592 * otherwise it is preferable to set a TTL once on the socket, and
593 * use that default TTL for all packets. This method does <B>not
594 * </B> alter the default TTL for the socket. Its behavior may be
595 * affected by <code>setInterface</code>.
596 *
597 * <p>If there is a security manager, this method first performs some
598 * security checks. First, if <code>p.getAddress().isMulticastAddress()</code>
599 * is true, this method calls the
600 * security manager's <code>checkMulticast</code> method
601 * with <code>p.getAddress()</code> and <code>ttl</code> as its arguments.
602 * If the evaluation of that expression is false,
603 * this method instead calls the security manager's
604 * <code>checkConnect</code> method with arguments
605 * <code>p.getAddress().getHostAddress()</code> and
606 * <code>p.getPort()</code>. Each call to a security manager method
607 * could result in a SecurityException if the operation is not allowed.
608 *
609 * @param p is the packet to be sent. The packet should contain
610 * the destination multicast ip address and the data to be sent.
611 * One does not need to be the member of the group to send
612 * packets to a destination multicast address.
613 * @param ttl optional time to live for multicast packet.
614 * default ttl is 1.
615 *
616 * @exception IOException is raised if an error occurs i.e
617 * error while setting ttl.
618 * @exception SecurityException if a security manager exists and its
619 * <code>checkMulticast</code> or <code>checkConnect</code>
620 * method doesn't allow the send.
621 *
622 * @deprecated Use the following code or its equivalent instead:
623 * ......
624 * int ttl = mcastSocket.getTimeToLive();
625 * mcastSocket.setTimeToLive(newttl);
626 * mcastSocket.send(p);
627 * mcastSocket.setTimeToLive(ttl);
628 * ......
629 *
630 * @see DatagramSocket#send
631 * @see DatagramSocket#receive
632 * @see SecurityManager#checkMulticast(java.net.InetAddress, byte)
633 * @see SecurityManager#checkConnect
634 */
635 @Deprecated
636 public void send(DatagramPacket p, byte ttl)
637 throws IOException {
638 if (isClosed())
639 throw new SocketException("Socket is closed");
640 checkAddress(p.getAddress(), "send");
641 synchronized(ttlLock) {
642 synchronized(p) {
643 if (connectState == ST_NOT_CONNECTED) {
644 // Security manager makes sure that the multicast address
645 // is allowed one and that the ttl used is less
646 // than the allowed maxttl.
647 SecurityManager security = System.getSecurityManager();
648 if (security != null) {
649 if (p.getAddress().isMulticastAddress()) {
650 security.checkMulticast(p.getAddress(), ttl);
651 } else {
652 security.checkConnect(p.getAddress().getHostAddress(),
653 p.getPort());
654 }
655 }
656 } else {
657 // we're connected
658 InetAddress packetAddress = null;
659 packetAddress = p.getAddress();
660 if (packetAddress == null) {
661 p.setAddress(connectedAddress);
662 p.setPort(connectedPort);
663 } else if ((!packetAddress.equals(connectedAddress)) ||
664 p.getPort() != connectedPort) {
665 throw new SecurityException("connected address and packet address" +
666 " differ");
667 }
668 }
669 byte dttl = getTTL();
670 try {
671 if (ttl != dttl) {
672 // set the ttl
673 getImpl().setTTL(ttl);
674 }
675 // call the datagram method to send
676 getImpl().send(p);
677 } finally {
678 // set it back to default
679 if (ttl != dttl) {
680 getImpl().setTTL(dttl);
681 }
682 }
683 } // synch p
684 } //synch ttl
685 } //method
686}