MulticastSocketTest.java revision 94279b64bcc98d8e28170204cf4aef0d803c7705
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.tests.java.net;
19
20import java.io.IOException;
21import java.net.BindException;
22import java.net.DatagramPacket;
23import java.net.Inet4Address;
24import java.net.Inet6Address;
25import java.net.InetAddress;
26import java.net.InetSocketAddress;
27import java.net.MulticastSocket;
28import java.net.NetworkInterface;
29import java.net.SocketAddress;
30import java.net.SocketException;
31import java.net.SocketTimeoutException;
32import java.util.ArrayList;
33import java.util.Enumeration;
34import java.util.List;
35
36public class MulticastSocketTest extends junit.framework.TestCase {
37
38    private static InetAddress lookup(String s) {
39        try {
40            return InetAddress.getByName(s);
41        } catch (IOException ex) {
42            throw new RuntimeException(ex);
43        }
44    }
45
46    // These IP addresses aren't inherently "good" or "bad"; they're just used like that.
47    // We use the "good" addresses for our actual group, and the "bad" addresses are for
48    // a group that we won't actually set up.
49
50    private static InetAddress GOOD_IPv4 = lookup("224.0.0.3");
51    private static InetAddress BAD_IPv4 = lookup("224.0.0.4");
52
53    private static InetAddress GOOD_IPv6 = lookup("ff05::7:7");
54    private static InetAddress BAD_IPv6 = lookup("ff05::7:8");
55
56    private NetworkInterface loopbackInterface;
57    private NetworkInterface ipv4NetworkInterface;
58    private NetworkInterface ipv6NetworkInterface;
59    private boolean supportsMulticast;
60
61    @Override
62    protected void setUp() throws Exception {
63        // The loopback interface isn't actually useful for sending/receiving multicast messages
64        // but it can be used as a dummy for tests where that does not matter.
65        loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
66        assertNotNull(loopbackInterface);
67        assertTrue(loopbackInterface.isLoopback());
68        assertFalse(loopbackInterface.supportsMulticast());
69
70        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
71        assertNotNull(interfaces);
72
73        // Determine if the device is marked to support multicast or not. If this propery is not
74        // set we assume the device has an interface capable of supporting multicast.
75        supportsMulticast = Boolean.valueOf(
76                System.getProperty("android.cts.device.multicast", "true"));
77        if (!supportsMulticast) {
78            return;
79        }
80
81        while (interfaces.hasMoreElements()
82                && (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) {
83            NetworkInterface nextInterface = interfaces.nextElement();
84            if (willWorkForMulticast(nextInterface)) {
85                Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
86                while (addresses.hasMoreElements()) {
87                    final InetAddress nextAddress = addresses.nextElement();
88                    if (nextAddress instanceof Inet6Address && ipv6NetworkInterface == null) {
89                        ipv6NetworkInterface = nextInterface;
90                    } else if (nextAddress instanceof Inet4Address && ipv4NetworkInterface == null) {
91                        ipv4NetworkInterface = nextInterface;
92                    }
93                }
94            }
95        }
96        assertTrue("Test environment must have at least one interface capable of multicast for IPv4"
97                + " and IPv6",
98                ipv4NetworkInterface != null && ipv6NetworkInterface != null);
99    }
100
101    public void test_Constructor() throws IOException {
102        if (!supportsMulticast) {
103            return;
104        }
105        // Regression test for 497.
106        MulticastSocket s = new MulticastSocket();
107        // Regression test for Harmony-1162.
108        assertTrue(s.getReuseAddress());
109
110        s.close();
111    }
112
113    public void test_ConstructorI() throws IOException {
114        if (!supportsMulticast) {
115            return;
116        }
117        MulticastSocket orig = new MulticastSocket();
118        int port = orig.getLocalPort();
119        orig.close();
120
121        MulticastSocket dup = new MulticastSocket(port);
122        // Regression test for Harmony-1162.
123        assertTrue(dup.getReuseAddress());
124        dup.close();
125    }
126
127    public void test_getInterface() throws Exception {
128        if (!supportsMulticast) {
129            return;
130        }
131        // Validate that we get the expected response when one was not set.
132        MulticastSocket mss = new MulticastSocket(0);
133        // We expect an ANY address in this case.
134        assertTrue(mss.getInterface().isAnyLocalAddress());
135
136        // Validate that we get the expected response when we set via setInterface.
137        Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
138        if (addresses.hasMoreElements()) {
139            InetAddress firstAddress = (InetAddress) addresses.nextElement();
140            mss.setInterface(firstAddress);
141            assertEquals("getNetworkInterface did not return interface set by setInterface",
142                    firstAddress, mss.getInterface());
143
144            mss.close();
145            mss = new MulticastSocket(0);
146            mss.setNetworkInterface(ipv4NetworkInterface);
147            assertEquals("getInterface did not return interface set by setNetworkInterface",
148                    ipv4NetworkInterface, NetworkInterface.getByInetAddress(mss.getInterface()));
149        }
150
151        mss.close();
152    }
153
154    public void test_getNetworkInterface() throws IOException {
155        if (!supportsMulticast) {
156            return;
157        }
158        // Validate that we get the expected response when one was not set.
159        MulticastSocket mss = new MulticastSocket(0);
160        NetworkInterface theInterface = mss.getNetworkInterface();
161        assertTrue(
162                "network interface returned wrong network interface when not set:" + theInterface,
163                theInterface.getInetAddresses().hasMoreElements());
164        InetAddress firstAddress = theInterface.getInetAddresses().nextElement();
165        // Validate we the first address in the network interface is the ANY address.
166        assertTrue(firstAddress.isAnyLocalAddress());
167
168        mss.setNetworkInterface(ipv4NetworkInterface);
169        assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
170                ipv4NetworkInterface, mss.getNetworkInterface());
171
172        mss.setNetworkInterface(loopbackInterface);
173        assertEquals(
174                "getNetworkInterface did not return network interface set by second"
175                        + " setNetworkInterface call",
176                loopbackInterface, mss.getNetworkInterface());
177        mss.close();
178
179        if (ipv6NetworkInterface != null) {
180            mss = new MulticastSocket(0);
181            mss.setNetworkInterface(ipv6NetworkInterface);
182            assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
183                    ipv6NetworkInterface, mss.getNetworkInterface());
184            mss.close();
185        }
186
187        // Validate that we get the expected response when we set via setInterface.
188        mss = new MulticastSocket(0);
189        Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
190        if (addresses.hasMoreElements()) {
191            firstAddress = (InetAddress) addresses.nextElement();
192            mss.setInterface(firstAddress);
193            assertEquals("getNetworkInterface did not return interface set by setInterface",
194                    ipv4NetworkInterface, mss.getNetworkInterface());
195        }
196        mss.close();
197    }
198
199    public void test_getTimeToLive() throws Exception {
200        if (!supportsMulticast) {
201            return;
202        }
203        MulticastSocket mss = new MulticastSocket();
204        mss.setTimeToLive(120);
205        assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
206        mss.setTimeToLive(220);
207        assertEquals("Returned incorrect 2nd TTL", 220, mss.getTimeToLive());
208        mss.close();
209    }
210
211    public void test_getTTL() throws Exception {
212        if (!supportsMulticast) {
213            return;
214        }
215        MulticastSocket mss = new MulticastSocket();
216        mss.setTTL((byte) 120);
217        assertEquals("Returned incorrect TTL", 120, mss.getTTL());
218        mss.close();
219    }
220
221    public void test_joinGroupLjava_net_InetAddress_IPv4() throws Exception {
222        if (!supportsMulticast) {
223            return;
224        }
225        test_joinGroupLjava_net_InetAddress(GOOD_IPv4);
226    }
227
228    public void test_joinGroupLjava_net_InetAddress_IPv6() throws Exception {
229        if (!supportsMulticast) {
230            return;
231        }
232        test_joinGroupLjava_net_InetAddress(GOOD_IPv6);
233    }
234
235    private void test_joinGroupLjava_net_InetAddress(InetAddress group) throws Exception {
236        MulticastSocket receivingSocket = createReceivingSocket(0);
237        receivingSocket.joinGroup(group);
238
239        String msg = "Hello World";
240        MulticastSocket sendingSocket = new MulticastSocket(receivingSocket.getLocalPort());
241        InetSocketAddress groupAddress =
242                new InetSocketAddress(group, receivingSocket.getLocalPort());
243        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
244        sendingSocket.send(sdp, (byte) 10 /* ttl */);
245
246        DatagramPacket rdp = createReceiveDatagramPacket();
247        receivingSocket.receive(rdp);
248        String receivedMessage = extractMessage(rdp);
249        assertEquals("Group member did not recv data", msg, receivedMessage);
250
251        sendingSocket.close();
252        receivingSocket.close();
253    }
254
255    public void test_joinGroup_null_null() throws Exception {
256        if (!supportsMulticast) {
257            return;
258        }
259        MulticastSocket mss = new MulticastSocket(0);
260        try {
261            mss.joinGroup(null, null);
262            fail();
263        } catch (IllegalArgumentException expected) {
264        }
265        mss.close();
266    }
267
268    public void test_joinGroup_non_multicast_address_IPv4() throws Exception {
269        if (!supportsMulticast) {
270            return;
271        }
272        MulticastSocket mss = new MulticastSocket(0);
273        try {
274            mss.joinGroup(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0), null);
275            fail();
276        } catch (IOException expected) {
277        }
278        mss.close();
279    }
280
281    public void test_joinGroup_non_multicast_address_IPv6() throws Exception {
282        if (!supportsMulticast) {
283            return;
284        }
285        MulticastSocket mss = new MulticastSocket(0);
286        try {
287            mss.joinGroup(new InetSocketAddress(InetAddress.getByName("::1"), 0), null);
288            fail();
289        } catch (IOException expected) {
290        }
291        mss.close();
292    }
293
294    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
295            throws Exception {
296        if (!supportsMulticast) {
297            return;
298        }
299        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
300                ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
301    }
302
303    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
304            throws Exception {
305        if (!supportsMulticast) {
306            return;
307        }
308        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
309                ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
310    }
311
312    private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
313            NetworkInterface networkInterface, InetAddress group, InetAddress group2)
314            throws Exception {
315        // Check that we can join a group using a null network interface.
316        MulticastSocket sendingSocket = new MulticastSocket(0);
317        SocketAddress groupSockAddr = new InetSocketAddress(group, sendingSocket.getLocalPort());
318        sendingSocket.joinGroup(groupSockAddr, null);
319        sendingSocket.setTimeToLive(2);
320
321        MulticastSocket receivingSocket = createReceivingSocket(0);
322        InetSocketAddress groupAddress =
323                new InetSocketAddress(group, receivingSocket.getLocalPort());
324        receivingSocket.joinGroup(groupAddress, networkInterface);
325
326        String msg = "Hello World";
327        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
328        sendingSocket.send(sdp);
329
330        DatagramPacket rdp = createReceiveDatagramPacket();
331        receivingSocket.receive(rdp);
332        // Now validate that we received the data as expected.
333        assertEquals("Group member did not recv data", msg, extractMessage(rdp));
334        receivingSocket.close();
335        sendingSocket.close();
336
337        receivingSocket = createReceivingSocket(0);
338        groupAddress = new InetSocketAddress(group, receivingSocket.getLocalPort());
339        receivingSocket.joinGroup(groupAddress, networkInterface);
340
341        sendingSocket = new MulticastSocket(0);
342        sendingSocket.setTimeToLive(10);
343        msg = "Hello World - Different Group";
344        InetSocketAddress group2Address =
345                new InetSocketAddress(group2, receivingSocket.getLocalPort());
346        sdp = createSendDatagramPacket(group2Address, msg);
347        sendingSocket.send(sdp);
348
349        rdp = createReceiveDatagramPacket();
350        try {
351            receivingSocket.receive(rdp);
352            fail("Expected timeout");
353        } catch (SocketTimeoutException expected) {
354        }
355
356        receivingSocket.close();
357        sendingSocket.close();
358    }
359
360    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
361        if (!supportsMulticast) {
362            return;
363        }
364        // Check that we can join on specific interfaces and that we only receive if data is
365        // received on that interface. This test is only really useful on devices with multiple
366        // non-loopback interfaces.
367
368        List<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
369        Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
370        while (theInterfaces.hasMoreElements()) {
371            NetworkInterface thisInterface = theInterfaces.nextElement();
372            // Skip interfaces that do not support multicast - there's no point in proving
373            // they cannot send / receive multicast messages.
374            if (willWorkForMulticast(thisInterface)) {
375                realInterfaces.add(thisInterface);
376            }
377        }
378
379        for (NetworkInterface thisInterface : realInterfaces) {
380            // Find a suitable group IP and interface to use to sent packets to thisInterface.
381            Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();
382
383            NetworkInterface sendingInterface = null;
384            InetAddress group = null;
385            if (addresses.hasMoreElements()) {
386                InetAddress firstAddress = addresses.nextElement();
387                if (firstAddress instanceof Inet4Address) {
388                    group = GOOD_IPv4;
389                    sendingInterface = ipv4NetworkInterface;
390                } else {
391                    // if this interface only seems to support IPV6 addresses
392                    group = GOOD_IPv6;
393                    sendingInterface = ipv6NetworkInterface;
394                }
395            }
396
397            // Create a receivingSocket which is joined to the group and has only asked for packets
398            // on thisInterface.
399            MulticastSocket receivingSocket = createReceivingSocket(0);
400            InetSocketAddress groupAddress =
401                    new InetSocketAddress(group, receivingSocket.getLocalPort());
402            receivingSocket.joinGroup(groupAddress, thisInterface);
403
404            // Now send out a packet on sendingInterface. We should only see the packet if we send
405            // it on thisInterface.
406            MulticastSocket sendingSocket = new MulticastSocket(0);
407            sendingSocket.setNetworkInterface(sendingInterface);
408            String msg = "Hello World - Again " + thisInterface.getName();
409            DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
410            sendingSocket.send(sdp);
411
412            DatagramPacket rdp = createReceiveDatagramPacket();
413            try {
414                receivingSocket.receive(rdp);
415
416                // If the packet is received....
417                assertEquals(thisInterface, sendingInterface);
418                assertEquals("Group member did not recv data when bound on specific interface",
419                        msg, extractMessage(rdp));
420            } catch (SocketTimeoutException e) {
421                // If the packet was not received...
422                assertTrue(!thisInterface.equals(sendingInterface));
423            }
424
425            receivingSocket.close();
426            sendingSocket.close();
427        }
428    }
429
430    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4()
431            throws Exception {
432        if (!supportsMulticast) {
433            return;
434        }
435        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
436                ipv4NetworkInterface, GOOD_IPv4);
437    }
438
439    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6()
440            throws Exception {
441        if (!supportsMulticast) {
442            return;
443        }
444        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
445                ipv6NetworkInterface, GOOD_IPv6);
446    }
447
448    private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
449            NetworkInterface networkInterface, InetAddress group) throws Exception {
450        // Validate that we can join the same address on two different interfaces but not on the
451        // same interface.
452        MulticastSocket mss = new MulticastSocket(0);
453        SocketAddress groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
454        mss.joinGroup(groupSockAddr, networkInterface);
455        mss.joinGroup(groupSockAddr, loopbackInterface);
456        try {
457            mss.joinGroup(groupSockAddr, networkInterface);
458            fail("Did not get expected exception when joining for second time on same interface");
459        } catch (IOException e) {
460        }
461        mss.close();
462    }
463
464    public void test_leaveGroupLjava_net_InetAddress_IPv4() throws Exception {
465        if (!supportsMulticast) {
466            return;
467        }
468        test_leaveGroupLjava_net_InetAddress(GOOD_IPv4);
469    }
470
471    public void test_leaveGroupLjava_net_InetAddress_IPv6() throws Exception {
472        if (!supportsMulticast) {
473            return;
474        }
475        test_leaveGroupLjava_net_InetAddress(GOOD_IPv6);
476    }
477
478    private void test_leaveGroupLjava_net_InetAddress(InetAddress group) throws Exception {
479        String msg = "Hello World";
480        MulticastSocket mss = new MulticastSocket(0);
481        InetSocketAddress groupAddress = new InetSocketAddress(group, mss.getLocalPort());
482        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
483        mss.send(sdp, (byte) 10 /* ttl */);
484        try {
485            // Try to leave a group we didn't join.
486            mss.leaveGroup(group);
487            fail();
488        } catch (IOException expected) {
489        }
490        mss.close();
491    }
492
493    public void test_leaveGroup_null_null() throws Exception {
494        if (!supportsMulticast) {
495            return;
496        }
497        MulticastSocket mss = new MulticastSocket(0);
498        try {
499            mss.leaveGroup(null, null);
500            fail();
501        } catch (IllegalArgumentException expected) {
502        }
503        mss.close();
504    }
505
506    public void test_leaveGroup_non_multicast_address_IPv4() throws Exception {
507        if (!supportsMulticast) {
508            return;
509        }
510        MulticastSocket mss = new MulticastSocket(0);
511        try {
512            mss.leaveGroup(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0), null);
513            fail();
514        } catch (IOException expected) {
515        }
516        mss.close();
517    }
518
519    public void test_leaveGroup_non_multicast_address_IPv6() throws Exception {
520        if (!supportsMulticast) {
521            return;
522        }
523        MulticastSocket mss = new MulticastSocket(0);
524        try {
525            mss.leaveGroup(new InetSocketAddress(InetAddress.getByName("::1"), 0), null);
526            fail();
527        } catch (IOException expected) {
528        }
529        mss.close();
530    }
531
532    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
533            throws Exception {
534        if (!supportsMulticast) {
535            return;
536        }
537        test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
538                ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
539    }
540
541    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
542            throws Exception {
543        if (!supportsMulticast) {
544            return;
545        }
546        test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
547                ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
548    }
549
550    private void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
551            NetworkInterface networkInterface, InetAddress group, InetAddress group2)
552            throws Exception {
553        SocketAddress groupSockAddr = null;
554        SocketAddress groupSockAddr2 = null;
555
556        MulticastSocket mss = new MulticastSocket(0);
557        groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
558        mss.joinGroup(groupSockAddr, null);
559        mss.leaveGroup(groupSockAddr, null);
560        try {
561            mss.leaveGroup(groupSockAddr, null);
562            fail("Did not get exception when trying to leave group that was already left");
563        } catch (IOException expected) {
564        }
565
566        groupSockAddr2 = new InetSocketAddress(group2, mss.getLocalPort());
567        mss.joinGroup(groupSockAddr, networkInterface);
568        try {
569            mss.leaveGroup(groupSockAddr2, networkInterface);
570            fail("Did not get exception when trying to leave group that was never joined");
571        } catch (IOException expected) {
572        }
573
574        mss.leaveGroup(groupSockAddr, networkInterface);
575
576        mss.joinGroup(groupSockAddr, networkInterface);
577        try {
578            mss.leaveGroup(groupSockAddr, loopbackInterface);
579            fail("Did not get exception when trying to leave group on wrong interface " +
580                    "joined on [" + networkInterface + "] left on [" + loopbackInterface + "]");
581        } catch (IOException expected) {
582        }
583    }
584
585    public void test_sendLjava_net_DatagramPacketB_IPv4() throws Exception {
586        if (!supportsMulticast) {
587            return;
588        }
589        test_sendLjava_net_DatagramPacketB(GOOD_IPv4);
590    }
591
592    public void test_sendLjava_net_DatagramPacketB_IPv6() throws Exception {
593        if (!supportsMulticast) {
594            return;
595        }
596        test_sendLjava_net_DatagramPacketB(GOOD_IPv6);
597    }
598
599    private void test_sendLjava_net_DatagramPacketB(InetAddress group) throws Exception {
600        String msg = "Hello World";
601        MulticastSocket sendingSocket = new MulticastSocket(0);
602        MulticastSocket receivingSocket = createReceivingSocket(sendingSocket.getLocalPort());
603        receivingSocket.joinGroup(group);
604
605        InetSocketAddress groupAddress = new InetSocketAddress(group, sendingSocket.getLocalPort());
606        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
607        sendingSocket.send(sdp, (byte) 10 /* ttl */);
608        sendingSocket.close();
609
610        DatagramPacket rdp = createReceiveDatagramPacket();
611        receivingSocket.receive(rdp);
612        String receivedMessage = extractMessage(rdp);
613        assertEquals("Failed to send data. Received " + rdp.getLength(), msg, receivedMessage);
614        receivingSocket.close();
615    }
616
617    public void test_setInterfaceLjava_net_InetAddress() throws Exception {
618        if (!supportsMulticast) {
619            return;
620        }
621        MulticastSocket mss = new MulticastSocket();
622        mss.setInterface(InetAddress.getLocalHost());
623        InetAddress theInterface = mss.getInterface();
624        // Under IPV6 we are not guaranteed to get the same address back as the address that was
625        // set, all we should be guaranteed is that we get an address on the same interface.
626        if (theInterface instanceof Inet6Address) {
627            assertEquals("Failed to return correct interface IPV6",
628                    NetworkInterface.getByInetAddress(mss.getInterface()),
629                    NetworkInterface.getByInetAddress(theInterface));
630        } else {
631            assertTrue("Failed to return correct interface IPV4 got:" + mss.getInterface() +
632                    " expected: " + InetAddress.getLocalHost(),
633                    mss.getInterface().equals(InetAddress.getLocalHost()));
634        }
635        mss.close();
636    }
637
638    public void test_setInterface_unbound_address_IPv4() throws Exception {
639        if (!supportsMulticast) {
640            return;
641        }
642        test_setInterface_unbound_address(GOOD_IPv4);
643    }
644
645    public void test_setInterface_unbound_address_IPv6() throws Exception {
646        if (!supportsMulticast) {
647            return;
648        }
649        test_setInterface_unbound_address(GOOD_IPv6);
650    }
651
652    // Regression test for Harmony-2410.
653    private void test_setInterface_unbound_address(InetAddress address) throws Exception {
654        MulticastSocket mss = new MulticastSocket();
655        try {
656            mss.setInterface(address);
657            fail();
658        } catch (SocketException expected) {
659        }
660        mss.close();
661    }
662
663    public void test_setNetworkInterfaceLjava_net_NetworkInterface_null() throws Exception {
664        if (!supportsMulticast) {
665            return;
666        }
667        // Validate that null interface is handled ok.
668        MulticastSocket mss = new MulticastSocket();
669        try {
670            mss.setNetworkInterface(null);
671            fail("No socket exception when we set then network interface with NULL");
672        } catch (SocketException ex) {
673        }
674        mss.close();
675    }
676
677    public void test_setNetworkInterfaceLjava_net_NetworkInterface_round_trip() throws Exception {
678        if (!supportsMulticast) {
679            return;
680        }
681        // Validate that we can get and set the interface.
682        MulticastSocket mss = new MulticastSocket();
683        mss.setNetworkInterface(ipv4NetworkInterface);
684        assertEquals("Interface did not seem to be set by setNeworkInterface",
685                ipv4NetworkInterface, mss.getNetworkInterface());
686        mss.close();
687    }
688
689    public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv4() throws Exception {
690        if (!supportsMulticast) {
691            return;
692        }
693        test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv4);
694    }
695
696    public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv6() throws Exception {
697        if (!supportsMulticast) {
698            return;
699        }
700        test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv6);
701    }
702
703    private void test_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group)
704            throws IOException, InterruptedException {
705        // Set up the receiving socket and join the group.
706        Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
707        while (theInterfaces.hasMoreElements()) {
708            NetworkInterface thisInterface = (NetworkInterface) theInterfaces.nextElement();
709            if (willWorkForMulticast(thisInterface)) {
710                if ((!(thisInterface.getInetAddresses().nextElement()).isLoopbackAddress())) {
711                    MulticastSocket receivingSocket = createReceivingSocket(0);
712                    InetSocketAddress groupAddress =
713                            new InetSocketAddress(group, receivingSocket.getLocalPort());
714                    receivingSocket.joinGroup(groupAddress, thisInterface);
715
716                    // Send the packets on a particular interface. The source address in the
717                    // received packet should be one of the addresses for the interface set.
718                    MulticastSocket sendingSocket = new MulticastSocket(0);
719                    sendingSocket.setNetworkInterface(thisInterface);
720                    String msg = thisInterface.getName();
721                    DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
722                    sendingSocket.send(sdp);
723
724                    DatagramPacket rdp = createReceiveDatagramPacket();
725                    receivingSocket.receive(rdp);
726                    String receivedMessage = extractMessage(rdp);
727                    assertEquals("Group member did not recv data sent on a specific interface",
728                            msg, receivedMessage);
729                    // Stop the server.
730                    receivingSocket.close();
731                    sendingSocket.close();
732                }
733            }
734        }
735    }
736
737    public void test_setTimeToLiveI() throws Exception {
738        if (!supportsMulticast) {
739            return;
740        }
741        MulticastSocket mss = new MulticastSocket();
742        mss.setTimeToLive(120);
743        assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
744        mss.setTimeToLive(220);
745        assertEquals("Returned incorrect 2nd TTL", 220, mss.getTimeToLive());
746        mss.close();
747    }
748
749    public void test_setTTLB() throws Exception {
750        if (!supportsMulticast) {
751            return;
752        }
753        MulticastSocket mss = new MulticastSocket();
754        mss.setTTL((byte) 120);
755        assertEquals("Failed to set TTL", 120, mss.getTTL());
756        mss.close();
757    }
758
759    public void test_ConstructorLjava_net_SocketAddress() throws Exception {
760        if (!supportsMulticast) {
761            return;
762        }
763        MulticastSocket ms = new MulticastSocket((SocketAddress) null);
764        assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
765        ms.bind(null);
766        assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
767        ms.close();
768        assertTrue("should be closed", ms.isClosed());
769
770        ms = new MulticastSocket(0);
771        assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
772        ms.close();
773        assertTrue("should be closed", ms.isClosed());
774
775        ms = new MulticastSocket(0);
776        assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
777        ms.close();
778        assertTrue("should be closed", ms.isClosed());
779
780        try {
781            new MulticastSocket(new InetSocketAddress("unresolvedname", 31415));
782            fail();
783        } catch (IOException expected) {
784        }
785
786        // Regression test for Harmony-1162.
787        InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 0);
788        MulticastSocket s = new MulticastSocket(addr);
789        assertTrue(s.getReuseAddress());
790        s.close();
791    }
792
793    public void test_getLoopbackMode() throws Exception {
794        if (!supportsMulticast) {
795            return;
796        }
797        MulticastSocket ms = new MulticastSocket(null);
798        assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
799        ms.getLoopbackMode();
800        assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
801        ms.close();
802        assertTrue("should be closed", ms.isClosed());
803    }
804
805    public void test_setLoopbackModeZ() throws Exception {
806        if (!supportsMulticast) {
807            return;
808        }
809        MulticastSocket ms = new MulticastSocket();
810        ms.setLoopbackMode(true);
811        assertTrue("loopback should be true", ms.getLoopbackMode());
812        ms.setLoopbackMode(false);
813        assertTrue("loopback should be false", !ms.getLoopbackMode());
814        ms.close();
815        assertTrue("should be closed", ms.isClosed());
816    }
817
818    public void test_setLoopbackModeSendReceive_IPv4() throws Exception {
819        if (!supportsMulticast) {
820            return;
821        }
822        test_setLoopbackModeSendReceive(GOOD_IPv4);
823    }
824
825    public void test_setLoopbackModeSendReceive_IPv6() throws Exception {
826        if (!supportsMulticast) {
827            return;
828        }
829        test_setLoopbackModeSendReceive(GOOD_IPv6);
830    }
831
832    private void test_setLoopbackModeSendReceive(InetAddress group) throws IOException {
833        // Test send receive.
834        final String message = "Hello, world!";
835
836        MulticastSocket socket = new MulticastSocket(0);
837        socket.setLoopbackMode(false); // false indicates doing loop back
838        socket.joinGroup(group);
839
840        // Send the datagram.
841        InetSocketAddress groupAddress = new InetSocketAddress(group, socket.getLocalPort());
842        DatagramPacket sendDatagram = createSendDatagramPacket(groupAddress, message);
843        socket.send(sendDatagram);
844
845        // Receive the datagram.
846        DatagramPacket recvDatagram = createReceiveDatagramPacket();
847        socket.setSoTimeout(5000); // Prevent eternal block in.
848        socket.receive(recvDatagram);
849        String recvMessage = extractMessage(recvDatagram);
850        assertEquals(message, recvMessage);
851        socket.close();
852    }
853
854    public void test_setReuseAddressZ() throws Exception {
855        if (!supportsMulticast) {
856            return;
857        }
858        // Test case were we to set ReuseAddress to false.
859        MulticastSocket theSocket1 = new MulticastSocket(null);
860        theSocket1.setReuseAddress(false);
861
862        MulticastSocket theSocket2 = new MulticastSocket(null);
863        theSocket2.setReuseAddress(false);
864
865        InetSocketAddress addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
866        theSocket1.bind(addr);
867        addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
868        try {
869            theSocket2.bind(addr);
870            fail("No exception when trying to connect to do duplicate socket bind with re-useaddr"
871                    + " set to false");
872        } catch (BindException expected) {
873        }
874        theSocket1.close();
875        theSocket2.close();
876
877        // Test case were we set it to true.
878        theSocket1 = new MulticastSocket(null);
879        theSocket2 = new MulticastSocket(null);
880        theSocket1.setReuseAddress(true);
881        theSocket2.setReuseAddress(true);
882        addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
883        theSocket1.bind(addr);
884        addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
885        theSocket2.bind(addr);
886
887        theSocket1.close();
888        theSocket2.close();
889
890        // Test the default case which we expect to be the same on all platforms.
891        theSocket1 = new MulticastSocket(null);
892        theSocket2 = new MulticastSocket(null);
893        addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
894        theSocket1.bind(addr);
895        addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
896        theSocket2.bind(addr);
897        theSocket1.close();
898        theSocket2.close();
899    }
900
901    private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
902        return iface.isUp()
903                // Typically loopback interfaces do not support multicast, but we rule them out
904                // explicitly anyway.
905                && !iface.isLoopback() && iface.supportsMulticast()
906                && iface.getInetAddresses().hasMoreElements();
907    }
908
909    private static MulticastSocket createReceivingSocket(int aPort) throws IOException {
910        MulticastSocket ms = new MulticastSocket(aPort);
911        ms.setSoTimeout(2000);
912        return ms;
913    }
914
915    private static DatagramPacket createReceiveDatagramPacket() {
916        byte[] rbuf = new byte[512];
917        return new DatagramPacket(rbuf, rbuf.length);
918    }
919
920    private static DatagramPacket createSendDatagramPacket(
921            InetSocketAddress groupAndPort, String msg) {
922        return new DatagramPacket(
923                msg.getBytes(), msg.length(), groupAndPort.getAddress(), groupAndPort.getPort());
924    }
925
926    private static String extractMessage(DatagramPacket rdp) {
927        return new String(rdp.getData(), 0, rdp.getLength());
928    }
929}
930