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