blob: 264e004e81f5e47933d5752d91e0145e22f58fac [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.harmony.tests.java.net;
import java.io.IOException;
import java.net.BindException;
import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class MulticastSocketTest extends junit.framework.TestCase {
private static InetAddress lookup(String s) {
try {
return InetAddress.getByName(s);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
// These IP addresses aren't inherently "good" or "bad"; they're just used like that.
// We use the "good" addresses for our actual group, and the "bad" addresses are for
// a group that we won't actually set up.
private static InetAddress GOOD_IPv4 = lookup("224.0.0.3");
private static InetAddress BAD_IPv4 = lookup("224.0.0.4");
private static InetAddress GOOD_IPv6 = lookup("ff05::7:7");
private static InetAddress BAD_IPv6 = lookup("ff05::7:8");
private NetworkInterface loopbackInterface;
private NetworkInterface ipv4NetworkInterface;
private NetworkInterface ipv6NetworkInterface;
private boolean supportsMulticast;
@Override
protected void setUp() throws Exception {
// The loopback interface isn't actually useful for sending/receiving multicast messages
// but it can be used as a dummy for tests where that does not matter.
loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
assertNotNull(loopbackInterface);
assertTrue(loopbackInterface.isLoopback());
assertFalse(loopbackInterface.supportsMulticast());
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
assertNotNull(interfaces);
// Determine if the device is marked to support multicast or not. If this propery is not
// set we assume the device has an interface capable of supporting multicast.
supportsMulticast = Boolean.valueOf(
System.getProperty("android.cts.device.multicast", "true"));
if (!supportsMulticast) {
return;
}
while (interfaces.hasMoreElements()
&& (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) {
NetworkInterface nextInterface = interfaces.nextElement();
if (willWorkForMulticast(nextInterface)) {
Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
final InetAddress nextAddress = addresses.nextElement();
if (nextAddress instanceof Inet6Address && ipv6NetworkInterface == null) {
ipv6NetworkInterface = nextInterface;
} else if (nextAddress instanceof Inet4Address
&& ipv4NetworkInterface == null) {
ipv4NetworkInterface = nextInterface;
}
}
}
}
assertTrue("Test environment must have at least one interface capable of multicast for IPv4"
+ " and IPv6",
ipv4NetworkInterface != null && ipv6NetworkInterface != null);
}
public void test_Constructor() throws IOException {
if (!supportsMulticast) {
return;
}
// Regression test for 497.
MulticastSocket s = new MulticastSocket();
// Regression test for Harmony-1162.
assertTrue(s.getReuseAddress());
s.close();
}
public void test_ConstructorI() throws IOException {
if (!supportsMulticast) {
return;
}
MulticastSocket orig = new MulticastSocket();
int port = orig.getLocalPort();
orig.close();
MulticastSocket dup = new MulticastSocket(port);
// Regression test for Harmony-1162.
assertTrue(dup.getReuseAddress());
dup.close();
}
public void test_getInterface() throws Exception {
if (!supportsMulticast) {
return;
}
// Validate that we get the expected response when one was not set.
MulticastSocket mss = new MulticastSocket(0);
// We expect an ANY address in this case.
assertTrue(mss.getInterface().isAnyLocalAddress());
// Validate that we get the expected response when we set via setInterface.
Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
if (addresses.hasMoreElements()) {
InetAddress firstAddress = (InetAddress) addresses.nextElement();
mss.setInterface(firstAddress);
assertEquals("getNetworkInterface did not return interface set by setInterface",
firstAddress, mss.getInterface());
mss.close();
mss = new MulticastSocket(0);
mss.setNetworkInterface(ipv4NetworkInterface);
assertEquals("getInterface did not return interface set by setNetworkInterface",
ipv4NetworkInterface, NetworkInterface.getByInetAddress(mss.getInterface()));
}
mss.close();
}
public void test_getNetworkInterface() throws IOException {
if (!supportsMulticast) {
return;
}
// Validate that we get the expected response when one was not set.
MulticastSocket mss = new MulticastSocket(0);
NetworkInterface theInterface = mss.getNetworkInterface();
assertTrue(
"network interface returned wrong network interface when not set:" + theInterface,
theInterface.getInetAddresses().hasMoreElements());
InetAddress firstAddress = theInterface.getInetAddresses().nextElement();
// Validate we the first address in the network interface is the ANY address.
assertTrue(firstAddress.isAnyLocalAddress());
mss.setNetworkInterface(ipv4NetworkInterface);
assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
ipv4NetworkInterface, mss.getNetworkInterface());
mss.setNetworkInterface(loopbackInterface);
assertEquals(
"getNetworkInterface did not return network interface set by second"
+ " setNetworkInterface call",
loopbackInterface, mss.getNetworkInterface());
mss.close();
if (ipv6NetworkInterface != null) {
mss = new MulticastSocket(0);
mss.setNetworkInterface(ipv6NetworkInterface);
assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
ipv6NetworkInterface, mss.getNetworkInterface());
mss.close();
}
// Validate that we get the expected response when we set via setInterface.
mss = new MulticastSocket(0);
Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
if (addresses.hasMoreElements()) {
firstAddress = (InetAddress) addresses.nextElement();
mss.setInterface(firstAddress);
assertEquals("getNetworkInterface did not return interface set by setInterface",
ipv4NetworkInterface, mss.getNetworkInterface());
}
mss.close();
}
public void test_getTimeToLive() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket();
mss.setTimeToLive(120);
assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
mss.setTimeToLive(220);
assertEquals("Returned incorrect 2nd TTL", 220, mss.getTimeToLive());
mss.close();
}
public void test_getTTL() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket();
mss.setTTL((byte) 120);
assertEquals("Returned incorrect TTL", 120, mss.getTTL());
mss.close();
}
public void test_joinGroupLjava_net_InetAddress_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
test_joinGroupLjava_net_InetAddress(GOOD_IPv4);
}
public void test_joinGroupLjava_net_InetAddress_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
test_joinGroupLjava_net_InetAddress(GOOD_IPv6);
}
private void test_joinGroupLjava_net_InetAddress(InetAddress group) throws Exception {
MulticastSocket receivingSocket = createReceivingSocket(0);
receivingSocket.joinGroup(group);
String msg = "Hello World";
MulticastSocket sendingSocket = new MulticastSocket(receivingSocket.getLocalPort());
InetSocketAddress groupAddress =
new InetSocketAddress(group, receivingSocket.getLocalPort());
DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
sendingSocket.send(sdp, (byte) 10 /* ttl */);
DatagramPacket rdp = createReceiveDatagramPacket();
receivingSocket.receive(rdp);
String receivedMessage = extractMessage(rdp);
assertEquals("Group member did not recv data", msg, receivedMessage);
sendingSocket.close();
receivingSocket.close();
}
public void test_joinGroup_null_null() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket(0);
try {
mss.joinGroup(null, null);
fail();
} catch (IllegalArgumentException expected) {
}
mss.close();
}
public void test_joinGroup_non_multicast_address_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket(0);
try {
mss.joinGroup(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0), null);
fail();
} catch (IOException expected) {
}
mss.close();
}
public void test_joinGroup_non_multicast_address_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket(0);
try {
mss.joinGroup(new InetSocketAddress(InetAddress.getByName("::1"), 0), null);
fail();
} catch (IOException expected) {
}
mss.close();
}
public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
throws Exception {
if (!supportsMulticast) {
return;
}
test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
}
public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
throws Exception {
if (!supportsMulticast) {
return;
}
test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
}
public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4_nullInterface()
throws Exception {
test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(null, GOOD_IPv4, BAD_IPv4);
}
public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6_nullInterface()
throws Exception {
test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(null, GOOD_IPv6, BAD_IPv6);
}
private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
NetworkInterface networkInterface, InetAddress group, InetAddress group2)
throws Exception {
// Create the sending socket and specify the interface to use as needed (otherwise use the
// default).
MulticastSocket sendingSocket = new MulticastSocket(0);
if (networkInterface != null) {
sendingSocket.setNetworkInterface(networkInterface);
}
sendingSocket.setTimeToLive(2);
MulticastSocket receivingSocket = createReceivingSocket(0);
InetSocketAddress groupAddress =
new InetSocketAddress(group, receivingSocket.getLocalPort());
// Join the group. A null network interface is valid and means "use default".
receivingSocket.joinGroup(groupAddress, networkInterface);
String msg = "Hello World";
DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
sendingSocket.send(sdp);
DatagramPacket rdp = createReceiveDatagramPacket();
receivingSocket.receive(rdp);
// Now validate that we received the data as expected.
assertEquals("Group member did not recv data", msg, extractMessage(rdp));
receivingSocket.close();
sendingSocket.close();
// Create the sending socket and specify the interface to use as needed (otherwise use the
// default).
sendingSocket = new MulticastSocket(0);
if (networkInterface != null) {
sendingSocket.setNetworkInterface(networkInterface);
}
sendingSocket.setTimeToLive(10);
receivingSocket = createReceivingSocket(0);
groupAddress = new InetSocketAddress(group, receivingSocket.getLocalPort());
// Join the group. A null network interface is valid and means "use default".
receivingSocket.joinGroup(groupAddress, networkInterface);
msg = "Hello World - Different Group";
InetSocketAddress group2Address =
new InetSocketAddress(group2, receivingSocket.getLocalPort());
sdp = createSendDatagramPacket(group2Address, msg);
sendingSocket.send(sdp);
rdp = createReceiveDatagramPacket();
try {
receivingSocket.receive(rdp);
fail("Expected timeout");
} catch (SocketTimeoutException expected) {
}
receivingSocket.close();
sendingSocket.close();
}
public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
if (!supportsMulticast) {
return;
}
// Check that we can join on specific interfaces and that we only receive if data is
// received on that interface. This test is only really useful on devices with multiple
// non-loopback interfaces.
List<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
while (theInterfaces.hasMoreElements()) {
NetworkInterface thisInterface = theInterfaces.nextElement();
// Skip interfaces that do not support multicast - there's no point in proving
// they cannot send / receive multicast messages.
if (willWorkForMulticast(thisInterface)) {
realInterfaces.add(thisInterface);
}
}
for (NetworkInterface thisInterface : realInterfaces) {
// Find a suitable group IP and interface to use to sent packets to thisInterface.
Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();
NetworkInterface sendingInterface = null;
InetAddress group = null;
if (addresses.hasMoreElements()) {
InetAddress firstAddress = addresses.nextElement();
if (firstAddress instanceof Inet4Address) {
group = GOOD_IPv4;
sendingInterface = ipv4NetworkInterface;
} else {
// if this interface only seems to support IPV6 addresses
group = GOOD_IPv6;
sendingInterface = ipv6NetworkInterface;
}
}
// Create a receivingSocket which is joined to the group and has only asked for packets
// on thisInterface.
MulticastSocket receivingSocket = createReceivingSocket(0);
InetSocketAddress groupAddress =
new InetSocketAddress(group, receivingSocket.getLocalPort());
receivingSocket.joinGroup(groupAddress, thisInterface);
// Now send out a packet on sendingInterface. We should only see the packet if we send
// it on thisInterface.
MulticastSocket sendingSocket = new MulticastSocket(0);
sendingSocket.setNetworkInterface(sendingInterface);
String msg = "Hello World - Again " + thisInterface.getName();
DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
sendingSocket.send(sdp);
DatagramPacket rdp = createReceiveDatagramPacket();
try {
receivingSocket.receive(rdp);
// If the packet is received....
assertEquals(thisInterface, sendingInterface);
assertEquals("Group member did not recv data when bound on specific interface",
msg, extractMessage(rdp));
} catch (SocketTimeoutException e) {
// If the packet was not received...
assertTrue(!thisInterface.equals(sendingInterface));
}
receivingSocket.close();
sendingSocket.close();
}
}
public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4()
throws Exception {
if (!supportsMulticast) {
return;
}
test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
ipv4NetworkInterface, GOOD_IPv4);
}
public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6()
throws Exception {
if (!supportsMulticast) {
return;
}
test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
ipv6NetworkInterface, GOOD_IPv6);
}
private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
NetworkInterface networkInterface, InetAddress group) throws Exception {
// Validate that we can join the same address on two different interfaces but not on the
// same interface.
MulticastSocket mss = new MulticastSocket(0);
SocketAddress groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
mss.joinGroup(groupSockAddr, networkInterface);
mss.joinGroup(groupSockAddr, loopbackInterface);
try {
mss.joinGroup(groupSockAddr, networkInterface);
fail("Did not get expected exception when joining for second time on same interface");
} catch (IOException e) {
}
mss.close();
}
public void test_leaveGroupLjava_net_InetAddress_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
test_leaveGroupLjava_net_InetAddress(GOOD_IPv4);
}
public void test_leaveGroupLjava_net_InetAddress_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
test_leaveGroupLjava_net_InetAddress(GOOD_IPv6);
}
private void test_leaveGroupLjava_net_InetAddress(InetAddress group) throws Exception {
String msg = "Hello World";
MulticastSocket mss = new MulticastSocket(0);
InetSocketAddress groupAddress = new InetSocketAddress(group, mss.getLocalPort());
DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
mss.send(sdp, (byte) 10 /* ttl */);
try {
// Try to leave a group we didn't join.
mss.leaveGroup(group);
fail();
} catch (IOException expected) {
}
mss.close();
}
public void test_leaveGroup_null_null() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket(0);
try {
mss.leaveGroup(null, null);
fail();
} catch (IllegalArgumentException expected) {
}
mss.close();
}
public void test_leaveGroup_non_multicast_address_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket(0);
try {
mss.leaveGroup(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0), null);
fail();
} catch (IOException expected) {
}
mss.close();
}
public void test_leaveGroup_non_multicast_address_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket(0);
try {
mss.leaveGroup(new InetSocketAddress(InetAddress.getByName("::1"), 0), null);
fail();
} catch (IOException expected) {
}
mss.close();
}
public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
throws Exception {
if (!supportsMulticast) {
return;
}
test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
}
public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
throws Exception {
if (!supportsMulticast) {
return;
}
test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
}
private void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
NetworkInterface networkInterface, InetAddress group, InetAddress group2)
throws Exception {
SocketAddress groupSockAddr = null;
SocketAddress groupSockAddr2 = null;
MulticastSocket mss = new MulticastSocket(0);
groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
mss.joinGroup(groupSockAddr, null);
mss.leaveGroup(groupSockAddr, null);
try {
mss.leaveGroup(groupSockAddr, null);
fail("Did not get exception when trying to leave group that was already left");
} catch (IOException expected) {
}
groupSockAddr2 = new InetSocketAddress(group2, mss.getLocalPort());
mss.joinGroup(groupSockAddr, networkInterface);
try {
mss.leaveGroup(groupSockAddr2, networkInterface);
fail("Did not get exception when trying to leave group that was never joined");
} catch (IOException expected) {
}
mss.leaveGroup(groupSockAddr, networkInterface);
mss.joinGroup(groupSockAddr, networkInterface);
try {
mss.leaveGroup(groupSockAddr, loopbackInterface);
fail("Did not get exception when trying to leave group on wrong interface " +
"joined on [" + networkInterface + "] left on [" + loopbackInterface + "]");
} catch (IOException expected) {
}
}
public void test_sendLjava_net_DatagramPacketB_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
test_sendLjava_net_DatagramPacketB(GOOD_IPv4);
}
public void test_sendLjava_net_DatagramPacketB_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
test_sendLjava_net_DatagramPacketB(GOOD_IPv6);
}
private void test_sendLjava_net_DatagramPacketB(InetAddress group) throws Exception {
String msg = "Hello World";
MulticastSocket sendingSocket = new MulticastSocket(0);
MulticastSocket receivingSocket = createReceivingSocket(sendingSocket.getLocalPort());
receivingSocket.joinGroup(group);
InetSocketAddress groupAddress = new InetSocketAddress(group, sendingSocket.getLocalPort());
DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
sendingSocket.send(sdp, (byte) 10 /* ttl */);
sendingSocket.close();
DatagramPacket rdp = createReceiveDatagramPacket();
receivingSocket.receive(rdp);
String receivedMessage = extractMessage(rdp);
assertEquals("Failed to send data. Received " + rdp.getLength(), msg, receivedMessage);
receivingSocket.close();
}
public void test_setInterfaceLjava_net_InetAddress() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket();
mss.setInterface(InetAddress.getLocalHost());
InetAddress theInterface = mss.getInterface();
// Under IPV6 we are not guaranteed to get the same address back as the address that was
// set, all we should be guaranteed is that we get an address on the same interface.
if (theInterface instanceof Inet6Address) {
assertEquals("Failed to return correct interface IPV6",
NetworkInterface.getByInetAddress(mss.getInterface()),
NetworkInterface.getByInetAddress(theInterface));
} else {
assertTrue("Failed to return correct interface IPV4 got:" + mss.getInterface() +
" expected: " + InetAddress.getLocalHost(),
mss.getInterface().equals(InetAddress.getLocalHost()));
}
mss.close();
}
public void test_setInterface_unbound_address_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
test_setInterface_unbound_address(GOOD_IPv4);
}
public void test_setInterface_unbound_address_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
test_setInterface_unbound_address(GOOD_IPv6);
}
// Regression test for Harmony-2410.
private void test_setInterface_unbound_address(InetAddress address) throws Exception {
MulticastSocket mss = new MulticastSocket();
try {
mss.setInterface(address);
fail();
} catch (SocketException expected) {
}
mss.close();
}
public void test_setNetworkInterfaceLjava_net_NetworkInterface_null() throws Exception {
if (!supportsMulticast) {
return;
}
// Validate that null interface is handled ok.
MulticastSocket mss = new MulticastSocket();
try {
mss.setNetworkInterface(null);
fail("No socket exception when we set then network interface with NULL");
} catch (SocketException ex) {
}
mss.close();
}
public void test_setNetworkInterfaceLjava_net_NetworkInterface_round_trip() throws Exception {
if (!supportsMulticast) {
return;
}
// Validate that we can get and set the interface.
MulticastSocket mss = new MulticastSocket();
mss.setNetworkInterface(ipv4NetworkInterface);
assertEquals("Interface did not seem to be set by setNeworkInterface",
ipv4NetworkInterface, mss.getNetworkInterface());
mss.close();
}
public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv4);
}
public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv6);
}
private void test_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group)
throws IOException, InterruptedException {
// Set up the receiving socket and join the group.
Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
while (theInterfaces.hasMoreElements()) {
NetworkInterface thisInterface = (NetworkInterface) theInterfaces.nextElement();
if (willWorkForMulticast(thisInterface)) {
if ((!(thisInterface.getInetAddresses().nextElement()).isLoopbackAddress())) {
MulticastSocket receivingSocket = createReceivingSocket(0);
InetSocketAddress groupAddress =
new InetSocketAddress(group, receivingSocket.getLocalPort());
receivingSocket.joinGroup(groupAddress, thisInterface);
// Send the packets on a particular interface. The source address in the
// received packet should be one of the addresses for the interface set.
MulticastSocket sendingSocket = new MulticastSocket(0);
sendingSocket.setNetworkInterface(thisInterface);
String msg = thisInterface.getName();
DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
sendingSocket.send(sdp);
DatagramPacket rdp = createReceiveDatagramPacket();
receivingSocket.receive(rdp);
String receivedMessage = extractMessage(rdp);
assertEquals("Group member did not recv data sent on a specific interface",
msg, receivedMessage);
// Stop the server.
receivingSocket.close();
sendingSocket.close();
}
}
}
}
public void test_setTimeToLiveI() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket();
mss.setTimeToLive(120);
assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
mss.setTimeToLive(220);
assertEquals("Returned incorrect 2nd TTL", 220, mss.getTimeToLive());
mss.close();
}
public void test_setTTLB() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket mss = new MulticastSocket();
mss.setTTL((byte) 120);
assertEquals("Failed to set TTL", 120, mss.getTTL());
mss.close();
}
public void test_ConstructorLjava_net_SocketAddress() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket ms = new MulticastSocket((SocketAddress) null);
assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
ms.bind(null);
assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
ms.close();
assertTrue("should be closed", ms.isClosed());
ms = new MulticastSocket(0);
assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
ms.close();
assertTrue("should be closed", ms.isClosed());
ms = new MulticastSocket(0);
assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
ms.close();
assertTrue("should be closed", ms.isClosed());
try {
new MulticastSocket(new InetSocketAddress("unresolvedname", 31415));
fail();
} catch (IOException expected) {
}
// Regression test for Harmony-1162.
InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 0);
MulticastSocket s = new MulticastSocket(addr);
assertTrue(s.getReuseAddress());
s.close();
}
public void test_getLoopbackMode() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket ms = new MulticastSocket(null);
assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
ms.getLoopbackMode();
assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
ms.close();
assertTrue("should be closed", ms.isClosed());
}
public void test_setLoopbackModeZ() throws Exception {
if (!supportsMulticast) {
return;
}
MulticastSocket ms = new MulticastSocket();
ms.setLoopbackMode(true);
assertTrue("loopback should be true", ms.getLoopbackMode());
ms.setLoopbackMode(false);
assertTrue("loopback should be false", !ms.getLoopbackMode());
ms.close();
assertTrue("should be closed", ms.isClosed());
}
public void test_setLoopbackModeSendReceive_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
test_setLoopbackModeSendReceive(GOOD_IPv4);
}
public void test_setLoopbackModeSendReceive_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
test_setLoopbackModeSendReceive(GOOD_IPv6);
}
private void test_setLoopbackModeSendReceive(InetAddress group) throws IOException {
// Test send receive.
final String message = "Hello, world!";
MulticastSocket socket = new MulticastSocket(0);
socket.setLoopbackMode(false); // false indicates doing loop back
socket.joinGroup(group);
// Send the datagram.
InetSocketAddress groupAddress = new InetSocketAddress(group, socket.getLocalPort());
DatagramPacket sendDatagram = createSendDatagramPacket(groupAddress, message);
socket.send(sendDatagram);
// Receive the datagram.
DatagramPacket recvDatagram = createReceiveDatagramPacket();
socket.setSoTimeout(5000); // Prevent eternal block in.
socket.receive(recvDatagram);
String recvMessage = extractMessage(recvDatagram);
assertEquals(message, recvMessage);
socket.close();
}
public void test_setReuseAddressZ() throws Exception {
if (!supportsMulticast) {
return;
}
// Test case were we to set ReuseAddress to false.
MulticastSocket theSocket1 = new MulticastSocket(null);
theSocket1.setReuseAddress(false);
MulticastSocket theSocket2 = new MulticastSocket(null);
theSocket2.setReuseAddress(false);
InetSocketAddress addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
theSocket1.bind(addr);
addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
try {
theSocket2.bind(addr);
fail("No exception when trying to connect to do duplicate socket bind with re-useaddr"
+ " set to false");
} catch (BindException expected) {
}
theSocket1.close();
theSocket2.close();
// Test case were we set it to true.
theSocket1 = new MulticastSocket(null);
theSocket2 = new MulticastSocket(null);
theSocket1.setReuseAddress(true);
theSocket2.setReuseAddress(true);
addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
theSocket1.bind(addr);
addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
theSocket2.bind(addr);
theSocket1.close();
theSocket2.close();
// Test the default case which we expect to be the same on all platforms.
theSocket1 = new MulticastSocket(null);
theSocket2 = new MulticastSocket(null);
addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
theSocket1.bind(addr);
addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
theSocket2.bind(addr);
theSocket1.close();
theSocket2.close();
}
private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
return iface.isUp()
// Typically loopback interfaces do not support multicast, but we rule them out
// explicitly anyway.
&& !iface.isLoopback()
// Point-to-point interfaces are known to cause problems. http://b/23279677
&& !iface.isPointToPoint()
&& iface.supportsMulticast()
&& iface.getInetAddresses().hasMoreElements();
}
private static MulticastSocket createReceivingSocket(int aPort) throws IOException {
MulticastSocket ms = new MulticastSocket(aPort);
ms.setSoTimeout(2000);
return ms;
}
private static DatagramPacket createReceiveDatagramPacket() {
byte[] rbuf = new byte[512];
return new DatagramPacket(rbuf, rbuf.length);
}
private static DatagramPacket createSendDatagramPacket(
InetSocketAddress groupAndPort, String msg) {
return new DatagramPacket(
msg.getBytes(), msg.length(), groupAndPort.getAddress(), groupAndPort.getPort());
}
private static String extractMessage(DatagramPacket rdp) {
return new String(rdp.getData(), 0, rdp.getLength());
}
}