1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package libcore.java.nio.channels; 18 19import junit.framework.AssertionFailedError; 20import junit.framework.TestCase; 21import java.io.IOException; 22import java.net.Inet4Address; 23import java.net.Inet6Address; 24import java.net.InetAddress; 25import java.net.InetSocketAddress; 26import java.net.InterfaceAddress; 27import java.net.NetworkInterface; 28import java.net.SocketAddress; 29import java.net.SocketException; 30import java.net.SocketTimeoutException; 31import java.net.StandardSocketOptions; 32import java.nio.ByteBuffer; 33import java.nio.channels.ClosedChannelException; 34import java.nio.channels.DatagramChannel; 35import java.nio.channels.MembershipKey; 36import java.util.ArrayList; 37import java.util.Enumeration; 38 39import libcore.io.IoBridge; 40 41import static android.system.OsConstants.POLLIN; 42 43/** 44 * Tests associated with multicast behavior of DatagramChannel. 45 * These tests require IPv6 multicasting enabled network. 46 */ 47public class DatagramChannelMulticastTest extends TestCase { 48 49 private static InetAddress lookup(String s) { 50 try { 51 return InetAddress.getByName(s); 52 } catch (IOException ex) { 53 throw new RuntimeException(ex); 54 } 55 } 56 57 // These IP addresses aren't inherently "good" or "bad"; they're just used like that. 58 // We use the "good" addresses for our actual group, and the "bad" addresses are for 59 // a group that we won't actually set up. 60 private static final InetAddress GOOD_MULTICAST_IPv4 = lookup("239.255.0.1"); 61 private static final InetAddress BAD_MULTICAST_IPv4 = lookup("239.255.0.2"); 62 private static final InetAddress GOOD_MULTICAST_IPv6 = lookup("ff05::7:7"); 63 private static final InetAddress BAD_MULTICAST_IPv6 = lookup("ff05::7:8"); 64 65 // Special addresses. 66 private static final InetAddress WILDCARD_IPv4 = lookup("0.0.0.0"); 67 private static final InetAddress WILDCARD_IPv6 = lookup("::"); 68 69 // Arbitrary unicast addresses. Used when the value doesn't actually matter. e.g. for source 70 // filters. 71 private static final InetAddress UNICAST_IPv4_1 = lookup("192.168.1.1"); 72 private static final InetAddress UNICAST_IPv4_2 = lookup("192.168.1.2"); 73 private static final InetAddress UNICAST_IPv6_1 = lookup("2001:db8::1"); 74 private static final InetAddress UNICAST_IPv6_2 = lookup("2001:db8::2"); 75 76 private NetworkInterface ipv4NetworkInterface; 77 private NetworkInterface ipv6NetworkInterface; 78 private NetworkInterface loopbackInterface; 79 80 private boolean supportsMulticast; 81 82 @Override 83 protected void setUp() throws Exception { 84 // The loopback interface isn't actually useful for sending/receiving multicast messages 85 // but it can be used as a dummy for tests where that does not matter. 86 loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress()); 87 assertNotNull(loopbackInterface); 88 assertTrue(loopbackInterface.isLoopback()); 89 assertFalse(loopbackInterface.supportsMulticast()); 90 91 Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); 92 93 // Determine if the device is marked to support multicast or not. If this propery is not 94 // set we assume the device has an interface capable of supporting multicast. 95 supportsMulticast = Boolean.parseBoolean( 96 System.getProperty("android.cts.device.multicast", "true")); 97 if (!supportsMulticast) { 98 return; 99 } 100 101 while (interfaces.hasMoreElements() 102 && (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) { 103 NetworkInterface nextInterface = interfaces.nextElement(); 104 if (willWorkForMulticast(nextInterface)) { 105 Enumeration<InetAddress> addresses = nextInterface.getInetAddresses(); 106 while (addresses.hasMoreElements()) { 107 final InetAddress nextAddress = addresses.nextElement(); 108 if (nextAddress instanceof Inet6Address && ipv6NetworkInterface == null) { 109 ipv6NetworkInterface = nextInterface; 110 } else if (nextAddress instanceof Inet4Address 111 && ipv4NetworkInterface == null) { 112 ipv4NetworkInterface = nextInterface; 113 } 114 } 115 } 116 } 117 118 if (ipv4NetworkInterface == null) { 119 fail("Test environment must have at least one network interface capable of IPv4" 120 + " multicast"); 121 } 122 if (ipv6NetworkInterface == null) { 123 fail("Test environment must have at least one network interface capable of IPv6" 124 + " multicast"); 125 } 126 } 127 128 public void test_open() throws IOException { 129 DatagramChannel dc = DatagramChannel.open(); 130 131 // Unlike MulticastSocket, DatagramChannel has SO_REUSEADDR set to false by default. 132 assertFalse(dc.getOption(StandardSocketOptions.SO_REUSEADDR)); 133 134 assertNull(dc.getLocalAddress()); 135 assertTrue(dc.isOpen()); 136 assertFalse(dc.isConnected()); 137 } 138 139 public void test_bind_null() throws Exception { 140 DatagramChannel dc = createReceiverChannel(); 141 assertNotNull(dc.getLocalAddress()); 142 assertTrue(dc.isOpen()); 143 assertFalse(dc.isConnected()); 144 145 dc.close(); 146 try { 147 dc.getLocalAddress(); 148 fail(); 149 } catch (ClosedChannelException expected) { 150 } 151 assertFalse(dc.isOpen()); 152 assertFalse(dc.isConnected()); 153 } 154 155 public void test_joinAnySource_afterClose() throws Exception { 156 if (!supportsMulticast) { 157 return; 158 } 159 DatagramChannel dc = createReceiverChannel(); 160 dc.close(); 161 try { 162 dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 163 fail(); 164 } catch (ClosedChannelException expected) { 165 } 166 } 167 168 public void test_joinAnySource_nullGroupAddress() throws Exception { 169 if (!supportsMulticast) { 170 return; 171 } 172 DatagramChannel dc = createReceiverChannel(); 173 try { 174 dc.join(null, ipv4NetworkInterface); 175 fail(); 176 } catch (NullPointerException expected) { 177 } 178 dc.close(); 179 } 180 181 public void test_joinAnySource_nullNetworkInterface() throws Exception { 182 if (!supportsMulticast) { 183 return; 184 } 185 DatagramChannel dc = createReceiverChannel(); 186 try { 187 dc.join(GOOD_MULTICAST_IPv4, null); 188 fail(); 189 } catch (NullPointerException expected) { 190 } 191 dc.close(); 192 } 193 194 public void test_joinAnySource_nonMulticastGroupAddress_IPv4() throws Exception { 195 if (!supportsMulticast) { 196 return; 197 } 198 DatagramChannel dc = createReceiverChannel(); 199 try { 200 dc.join(UNICAST_IPv4_1, ipv4NetworkInterface); 201 fail(); 202 } catch (IllegalArgumentException expected) { 203 } 204 dc.close(); 205 } 206 207 public void test_joinAnySource_nonMulticastGroupAddress_IPv6() throws Exception { 208 if (!supportsMulticast) { 209 return; 210 } 211 DatagramChannel dc = createReceiverChannel(); 212 try { 213 dc.join(UNICAST_IPv6_1, ipv6NetworkInterface); 214 fail(); 215 } catch (IllegalArgumentException expected) { 216 } 217 dc.close(); 218 } 219 220 public void test_joinAnySource_IPv4() throws Exception { 221 check_joinAnySource(GOOD_MULTICAST_IPv4, BAD_MULTICAST_IPv4, ipv4NetworkInterface); 222 } 223 224 public void test_joinAnySource_IPv6() throws Exception { 225 check_joinAnySource(GOOD_MULTICAST_IPv6, BAD_MULTICAST_IPv6, ipv6NetworkInterface); 226 } 227 228 private void check_joinAnySource(InetAddress group, InetAddress group2, 229 NetworkInterface networkInterface) throws Exception { 230 if (!supportsMulticast) { 231 return; 232 } 233 // Set up a receiver join the group on ipv4NetworkInterface 234 DatagramChannel receiverChannel = createReceiverChannel(); 235 InetSocketAddress localAddress = (InetSocketAddress) receiverChannel.getLocalAddress(); 236 receiverChannel.join(group, networkInterface); 237 238 String msg = "Hello World"; 239 sendMulticastMessage(group, localAddress.getPort(), msg, networkInterface); 240 241 // now verify that we received the data as expected 242 ByteBuffer recvBuffer = ByteBuffer.allocate(100); 243 SocketAddress sourceAddress = receiverChannel.receive(recvBuffer); 244 assertNotNull(sourceAddress); 245 assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position())); 246 247 // now verify that we didn't receive the second message 248 String msg2 = "Hello World - Different Group"; 249 sendMulticastMessage(group2, localAddress.getPort(), msg2, networkInterface); 250 recvBuffer.position(0); 251 SocketAddress sourceAddress2 = receiverChannel.receive(recvBuffer); 252 assertNull(sourceAddress2); 253 254 receiverChannel.close(); 255 } 256 257 public void test_joinAnySource_processLimit() throws Exception { 258 if (!supportsMulticast) { 259 return; 260 } 261 DatagramChannel dc = createReceiverChannel(); 262 for (byte i = 1; i <= 25; i++) { 263 InetAddress groupAddress = Inet4Address.getByName("239.255.0." + i); 264 try { 265 dc.join(groupAddress, ipv4NetworkInterface); 266 } catch (SocketException e) { 267 // There is a limit, that's ok according to the RI docs. For this test a lower bound of 20 268 // is used, which appears to be the default linux limit. 269 // See /proc/sys/net/ipv4/igmp_max_memberships 270 assertTrue(i > 20); 271 break; 272 } 273 } 274 275 dc.close(); 276 } 277 278 public void test_joinAnySource_blockLimit() throws Exception { 279 if (!supportsMulticast) { 280 return; 281 } 282 DatagramChannel dc = createReceiverChannel(); 283 MembershipKey key = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 284 for (byte i = 1; i <= 15; i++) { 285 InetAddress sourceAddress = Inet4Address.getByName("10.0.0." + i); 286 try { 287 key.block(sourceAddress); 288 } catch (SocketException e) { 289 // There is a limit, that's ok according to the RI docs. For this test a lower bound of 10 290 // is used, which appears to be the default linux limit. 291 // See /proc/sys/net/ipv4/igmp_max_msf 292 assertTrue(i > 10); 293 break; 294 } 295 } 296 297 dc.close(); 298 } 299 300 /** Confirms that calling join() does not cause an implicit bind() to take place. */ 301 public void test_joinAnySource_doesNotCauseBind() throws Exception { 302 if (!supportsMulticast) { 303 return; 304 } 305 DatagramChannel dc = DatagramChannel.open(); 306 dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 307 assertNull(dc.getLocalAddress()); 308 309 dc.close(); 310 } 311 312 public void test_joinAnySource_networkInterfaces() throws Exception { 313 if (!supportsMulticast) { 314 return; 315 } 316 // Check that we can join on specific interfaces and that we only receive if data is 317 // received on that interface. This test is only really useful on devices with multiple 318 // non-loopback interfaces. 319 320 ArrayList<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>(); 321 Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces(); 322 while (theInterfaces.hasMoreElements()) { 323 NetworkInterface thisInterface = theInterfaces.nextElement(); 324 if (thisInterface.getInetAddresses().hasMoreElements()) { 325 realInterfaces.add(thisInterface); 326 } 327 } 328 329 for (int i = 0; i < realInterfaces.size(); i++) { 330 NetworkInterface thisInterface = realInterfaces.get(i); 331 if (!thisInterface.supportsMulticast()) { 332 // Skip interfaces that do not support multicast - there's no point in proving 333 // they cannot send / receive multicast messages. 334 continue; 335 } 336 337 // get the first address on the interface 338 339 // start server which is joined to the group and has 340 // only asked for packets on this interface 341 Enumeration<InetAddress> addresses = thisInterface.getInetAddresses(); 342 343 NetworkInterface sendingInterface = null; 344 InetAddress group = null; 345 if (addresses.hasMoreElements()) { 346 InetAddress firstAddress = addresses.nextElement(); 347 if (firstAddress instanceof Inet4Address) { 348 group = GOOD_MULTICAST_IPv4; 349 sendingInterface = ipv4NetworkInterface; 350 } else { 351 // if this interface only seems to support IPV6 addresses 352 group = GOOD_MULTICAST_IPv6; 353 sendingInterface = ipv6NetworkInterface; 354 } 355 } 356 357 DatagramChannel dc = createReceiverChannel(); 358 InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress(); 359 dc.join(group, thisInterface); 360 361 // Now send out a package on sendingInterface. We should only see the packet if we send 362 // it on the same interface we are listening on (thisInterface). 363 String msg = "Hello World - Again" + thisInterface.getName(); 364 sendMulticastMessage(group, localAddress.getPort(), msg, sendingInterface); 365 366 ByteBuffer recvBuffer = ByteBuffer.allocate(100); 367 SocketAddress sourceAddress = dc.receive(recvBuffer); 368 if (thisInterface.equals(sendingInterface)) { 369 assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position())); 370 } else { 371 assertNull(sourceAddress); 372 } 373 374 dc.close(); 375 } 376 } 377 378 /** Confirms that the scope of each membership is network interface-level. */ 379 public void test_join_canMixTypesOnDifferentInterfaces() throws Exception { 380 if (!supportsMulticast) { 381 return; 382 } 383 DatagramChannel dc = DatagramChannel.open(); 384 MembershipKey membershipKey1 = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 385 MembershipKey membershipKey2 = dc.join(GOOD_MULTICAST_IPv4, loopbackInterface, UNICAST_IPv4_1); 386 assertNotSame(membershipKey1, membershipKey2); 387 388 dc.close(); 389 } 390 391 392 private DatagramChannel createReceiverChannel() throws Exception { 393 DatagramChannel dc = DatagramChannel.open(); 394 dc.bind(null /* leave the OS to determine the port, and use the wildcard address */); 395 configureChannelForReceiving(dc); 396 return dc; 397 } 398 399 public void test_joinAnySource_multiple_joins_IPv4() 400 throws Exception { 401 check_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 402 } 403 404 public void test_joinAnySource_multiple_joins_IPv6() 405 throws Exception { 406 check_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv6, ipv6NetworkInterface); 407 } 408 409 private void check_joinAnySource_multiple_joins(InetAddress group, 410 NetworkInterface networkInterface) throws Exception { 411 if (!supportsMulticast) { 412 return; 413 } 414 DatagramChannel dc = createReceiverChannel(); 415 416 MembershipKey membershipKey1 = dc.join(group, networkInterface); 417 418 MembershipKey membershipKey2 = dc.join(group, loopbackInterface); 419 assertFalse(membershipKey1.equals(membershipKey2)); 420 421 MembershipKey membershipKey1_2 = dc.join(group, networkInterface); 422 assertEquals(membershipKey1, membershipKey1_2); 423 424 dc.close(); 425 } 426 427 public void test_joinAnySource_multicastLoopOption_IPv4() throws Exception { 428 check_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 429 } 430 431 public void test_multicastLoopOption_IPv6() throws Exception { 432 check_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv6, ipv6NetworkInterface); 433 } 434 435 private void check_joinAnySource_multicastLoopOption(InetAddress group, 436 NetworkInterface networkInterface) throws Exception { 437 if (!supportsMulticast) { 438 return; 439 } 440 final String message = "Hello, world!"; 441 442 DatagramChannel dc = createReceiverChannel(); 443 dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true /* enable loop */); 444 dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface); 445 configureChannelForReceiving(dc); 446 dc.join(group, networkInterface); 447 448 InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress(); 449 450 // send the datagram 451 byte[] sendData = message.getBytes(); 452 ByteBuffer sendBuffer = ByteBuffer.wrap(sendData); 453 dc.send(sendBuffer, new InetSocketAddress(group, localAddress.getPort())); 454 455 // receive the datagram 456 ByteBuffer recvBuffer = ByteBuffer.allocate(100); 457 SocketAddress sourceAddress = dc.receive(recvBuffer); 458 assertNotNull(sourceAddress); 459 460 String recvMessage = new String(recvBuffer.array(), 0, recvBuffer.position()); 461 assertEquals(message, recvMessage); 462 463 // Turn off loop 464 dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false /* enable loopback */); 465 466 // send another datagram 467 recvBuffer.position(0); 468 ByteBuffer sendBuffer2 = ByteBuffer.wrap(sendData); 469 dc.send(sendBuffer2, new InetSocketAddress(group, localAddress.getPort())); 470 471 SocketAddress sourceAddress2 = dc.receive(recvBuffer); 472 assertNull(sourceAddress2); 473 474 dc.close(); 475 } 476 477 public void testMembershipKeyAccessors_IPv4() throws Exception { 478 checkMembershipKeyAccessors(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 479 } 480 481 public void testMembershipKeyAccessors_IPv6() throws Exception { 482 checkMembershipKeyAccessors(GOOD_MULTICAST_IPv6, ipv6NetworkInterface); 483 } 484 485 private void checkMembershipKeyAccessors(InetAddress group, 486 NetworkInterface networkInterface) throws Exception { 487 if (!supportsMulticast) { 488 return; 489 } 490 DatagramChannel dc = createReceiverChannel(); 491 492 MembershipKey key = dc.join(group, networkInterface); 493 assertSame(dc, key.channel()); 494 assertSame(group, key.group()); 495 assertTrue(key.isValid()); 496 assertSame(networkInterface, key.networkInterface()); 497 assertNull(key.sourceAddress()); 498 dc.close(); 499 } 500 501 public void test_dropAnySource_twice_IPv4() throws Exception { 502 check_dropAnySource_twice(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 503 } 504 505 public void test_dropAnySource_twice_IPv6() throws Exception { 506 check_dropAnySource_twice(GOOD_MULTICAST_IPv6, ipv6NetworkInterface); 507 } 508 509 private void check_dropAnySource_twice(InetAddress group, 510 NetworkInterface networkInterface) throws Exception { 511 if (!supportsMulticast) { 512 return; 513 } 514 DatagramChannel dc = createReceiverChannel(); 515 MembershipKey membershipKey = dc.join(group, networkInterface); 516 517 assertTrue(membershipKey.isValid()); 518 membershipKey.drop(); 519 assertFalse(membershipKey.isValid()); 520 521 // Try to leave a group we are no longer a member of - should do nothing. 522 membershipKey.drop(); 523 524 dc.close(); 525 } 526 527 public void test_close_invalidatesMembershipKey() throws Exception { 528 if (!supportsMulticast) { 529 return; 530 } 531 DatagramChannel dc = createReceiverChannel(); 532 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 533 534 assertTrue(membershipKey.isValid()); 535 536 dc.close(); 537 538 assertFalse(membershipKey.isValid()); 539 } 540 541 public void test_block_null() throws Exception { 542 if (!supportsMulticast) { 543 return; 544 } 545 DatagramChannel dc = createReceiverChannel(); 546 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 547 try { 548 membershipKey.block(null); 549 fail(); 550 } catch (NullPointerException expected) { 551 } 552 553 dc.close(); 554 } 555 556 public void test_block_mixedAddressTypes_IPv4() throws Exception { 557 if (!supportsMulticast) { 558 return; 559 } 560 DatagramChannel dc = createReceiverChannel(); 561 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 562 try { 563 membershipKey.block(UNICAST_IPv6_1); 564 fail(); 565 } catch (IllegalArgumentException expected) { 566 } 567 568 dc.close(); 569 } 570 571 public void test_block_mixedAddressTypes_IPv6() throws Exception { 572 if (!supportsMulticast) { 573 return; 574 } 575 DatagramChannel dc = createReceiverChannel(); 576 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface); 577 try { 578 membershipKey.block(UNICAST_IPv4_1); 579 fail(); 580 } catch (IllegalArgumentException expected) { 581 } 582 583 dc.close(); 584 } 585 586 public void test_block_cannotBlockWithSourceSpecificMembership() throws Exception { 587 if (!supportsMulticast) { 588 return; 589 } 590 DatagramChannel dc = createReceiverChannel(); 591 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1); 592 try { 593 membershipKey.block(UNICAST_IPv4_2); 594 fail(); 595 } catch (IllegalStateException expected) { 596 } 597 598 dc.close(); 599 } 600 601 public void test_block_multipleBlocksIgnored() throws Exception { 602 if (!supportsMulticast) { 603 return; 604 } 605 DatagramChannel dc = createReceiverChannel(); 606 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 607 membershipKey.block(UNICAST_IPv4_1); 608 609 MembershipKey membershipKey2 = membershipKey.block(UNICAST_IPv4_1); 610 assertSame(membershipKey2, membershipKey); 611 612 dc.close(); 613 } 614 615 public void test_block_wildcardAddress() throws Exception { 616 if (!supportsMulticast) { 617 return; 618 } 619 DatagramChannel dc = createReceiverChannel(); 620 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 621 try { 622 membershipKey.block(WILDCARD_IPv4); 623 fail(); 624 } catch (IllegalArgumentException expected) { 625 } 626 627 dc.close(); 628 } 629 630 public void test_unblock_multipleUnblocksFail() throws Exception { 631 if (!supportsMulticast) { 632 return; 633 } 634 DatagramChannel dc = createReceiverChannel(); 635 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 636 637 try { 638 membershipKey.unblock(UNICAST_IPv4_1); 639 fail(); 640 } catch (IllegalStateException expected) { 641 } 642 643 assertTrue(membershipKey.isValid()); 644 645 membershipKey.block(UNICAST_IPv4_1); 646 membershipKey.unblock(UNICAST_IPv4_1); 647 648 try { 649 membershipKey.unblock(UNICAST_IPv4_1); 650 fail(); 651 } catch (IllegalStateException expected) { 652 } 653 654 dc.close(); 655 } 656 657 public void test_unblock_null() throws Exception { 658 if (!supportsMulticast) { 659 return; 660 } 661 DatagramChannel dc = createReceiverChannel(); 662 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 663 membershipKey.block(UNICAST_IPv4_1); 664 665 try { 666 membershipKey.unblock(null); 667 fail(); 668 } catch (IllegalStateException expected) { 669 // Either of these exceptions are fine 670 } catch (NullPointerException expected) { 671 // Either of these exception are fine 672 } 673 674 dc.close(); 675 } 676 677 public void test_unblock_mixedAddressTypes_IPv4() throws Exception { 678 if (!supportsMulticast) { 679 return; 680 } 681 DatagramChannel dc = createReceiverChannel(); 682 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface); 683 try { 684 membershipKey.unblock(UNICAST_IPv6_1); 685 fail(); 686 } catch (IllegalStateException expected) { 687 // Either of these exceptions are fine 688 } catch (IllegalArgumentException expected) { 689 // Either of these exceptions are fine 690 } 691 692 dc.close(); 693 } 694 695 public void test_unblock_mixedAddressTypes_IPv6() throws Exception { 696 if (!supportsMulticast) { 697 return; 698 } 699 DatagramChannel dc = createReceiverChannel(); 700 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface); 701 try { 702 membershipKey.unblock(UNICAST_IPv4_1); 703 fail(); 704 } catch (IllegalStateException expected) { 705 // Either of these exceptions are fine 706 } catch (IllegalArgumentException expected) { 707 // Either of these exceptions are fine 708 } 709 710 dc.close(); 711 } 712 713 /** Checks that block() works when the receiver is bound to the multicast group address */ 714 public void test_block_filtersAsExpected_groupBind_ipv4() throws Exception { 715 if (!supportsMulticast) { 716 return; 717 } 718 InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface); 719 check_block_filtersAsExpected( 720 ipv4LocalAddress /* senderBindAddress */, 721 GOOD_MULTICAST_IPv4 /* receiverBindAddress */, 722 GOOD_MULTICAST_IPv4 /* groupAddress */, 723 ipv4NetworkInterface); 724 } 725 726 /** Checks that block() works when the receiver is bound to the multicast group address */ 727 public void test_block_filtersAsExpected_groupBind_ipv6() throws Exception { 728 if (!supportsMulticast) { 729 return; 730 } 731 InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface); 732 check_block_filtersAsExpected( 733 ipv6LocalAddress /* senderBindAddress */, 734 GOOD_MULTICAST_IPv6 /* receiverBindAddress */, 735 GOOD_MULTICAST_IPv6 /* groupAddress */, 736 ipv6NetworkInterface); 737 } 738 739 /** Checks that block() works when the receiver is bound to the "any" address */ 740 public void test_block_filtersAsExpected_anyBind_ipv4() throws Exception { 741 if (!supportsMulticast) { 742 return; 743 } 744 InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface); 745 check_block_filtersAsExpected( 746 ipv4LocalAddress /* senderBindAddress */, 747 WILDCARD_IPv4 /* receiverBindAddress */, 748 GOOD_MULTICAST_IPv4 /* groupAddress */, 749 ipv4NetworkInterface); 750 } 751 752 /** Checks that block() works when the receiver is bound to the "any" address */ 753 public void test_block_filtersAsExpected_anyBind_ipv6() throws Exception { 754 if (!supportsMulticast) { 755 return; 756 } 757 InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface); 758 check_block_filtersAsExpected( 759 ipv6LocalAddress /* senderBindAddress */, 760 WILDCARD_IPv6 /* receiverBindAddress */, 761 GOOD_MULTICAST_IPv6 /* groupAddress */, 762 ipv6NetworkInterface); 763 } 764 765 private void check_block_filtersAsExpected( 766 InetAddress senderBindAddress, InetAddress receiverBindAddress, 767 InetAddress groupAddress, NetworkInterface networkInterface) 768 throws Exception { 769 DatagramChannel sendingChannel = DatagramChannel.open(); 770 // In order to block a sender the sender's address must be known. The sendingChannel is 771 // explicitly bound to a known, non-loopback address. 772 sendingChannel.bind(new InetSocketAddress(senderBindAddress, 0)); 773 InetSocketAddress sendingAddress = (InetSocketAddress) sendingChannel.getLocalAddress(); 774 775 DatagramChannel receivingChannel = DatagramChannel.open(); 776 configureChannelForReceiving(receivingChannel); 777 receivingChannel.bind( 778 new InetSocketAddress(receiverBindAddress, 0) /* local port left to the OS to determine */); 779 InetSocketAddress localReceivingAddress = 780 (InetSocketAddress) receivingChannel.getLocalAddress(); 781 InetSocketAddress groupSocketAddress = 782 new InetSocketAddress(groupAddress, localReceivingAddress.getPort()); 783 MembershipKey membershipKey = 784 receivingChannel.join(groupSocketAddress.getAddress(), networkInterface); 785 786 ByteBuffer receiveBuffer = ByteBuffer.allocate(10); 787 788 // Send a message. It should be received. 789 String msg1 = "Hello1"; 790 sendMessage(sendingChannel, msg1, groupSocketAddress); 791 IoBridge.poll(receivingChannel.socket().getFileDescriptor$(), POLLIN, 1000); 792 InetSocketAddress sourceAddress1 = (InetSocketAddress) receivingChannel.receive(receiveBuffer); 793 assertEquals(sourceAddress1, sendingAddress); 794 assertEquals(msg1, new String(receiveBuffer.array(), 0, receiveBuffer.position())); 795 796 // Now block the sender 797 membershipKey.block(sendingAddress.getAddress()); 798 799 // Send a message. It should be filtered. 800 String msg2 = "Hello2"; 801 sendMessage(sendingChannel, msg2, groupSocketAddress); 802 try { 803 IoBridge.poll(receivingChannel.socket().getFileDescriptor$(), POLLIN, 1000); 804 fail(); 805 } catch (SocketTimeoutException expected) { } 806 receiveBuffer.position(0); 807 InetSocketAddress sourceAddress2 = (InetSocketAddress) receivingChannel.receive(receiveBuffer); 808 assertNull(sourceAddress2); 809 810 // Now unblock the sender 811 membershipKey.unblock(sendingAddress.getAddress()); 812 813 // Send a message. It should be received. 814 String msg3 = "Hello3"; 815 sendMessage(sendingChannel, msg3, groupSocketAddress); 816 IoBridge.poll(receivingChannel.socket().getFileDescriptor$(), POLLIN, 1000); 817 receiveBuffer.position(0); 818 InetSocketAddress sourceAddress3 = (InetSocketAddress) receivingChannel.receive(receiveBuffer); 819 assertEquals(sourceAddress3, sendingAddress); 820 assertEquals(msg3, new String(receiveBuffer.array(), 0, receiveBuffer.position())); 821 822 sendingChannel.close(); 823 receivingChannel.close(); 824 } 825 826 public void test_joinSourceSpecific_nullGroupAddress() throws Exception { 827 if (!supportsMulticast) { 828 return; 829 } 830 DatagramChannel dc = createReceiverChannel(); 831 try { 832 dc.join(null, ipv4NetworkInterface, UNICAST_IPv4_1); 833 fail(); 834 } catch (NullPointerException expected) { 835 } 836 dc.close(); 837 } 838 839 public void test_joinSourceSpecific_afterClose() throws Exception { 840 if (!supportsMulticast) { 841 return; 842 } 843 DatagramChannel dc = createReceiverChannel(); 844 dc.close(); 845 try { 846 dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1); 847 fail(); 848 } catch (ClosedChannelException expected) { 849 } 850 } 851 852 public void test_joinSourceSpecific_nullNetworkInterface() throws Exception { 853 if (!supportsMulticast) { 854 return; 855 } 856 DatagramChannel dc = createReceiverChannel(); 857 try { 858 dc.join(GOOD_MULTICAST_IPv4, null, UNICAST_IPv4_1); 859 fail(); 860 } catch (NullPointerException expected) { 861 } 862 dc.close(); 863 } 864 865 public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv4() throws Exception { 866 if (!supportsMulticast) { 867 return; 868 } 869 DatagramChannel dc = createReceiverChannel(); 870 try { 871 dc.join(UNICAST_IPv4_1, ipv4NetworkInterface, UNICAST_IPv4_1); 872 fail(); 873 } catch (IllegalArgumentException expected) { 874 } 875 dc.close(); 876 } 877 878 public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv6() throws Exception { 879 if (!supportsMulticast) { 880 return; 881 } 882 DatagramChannel dc = createReceiverChannel(); 883 try { 884 dc.join(UNICAST_IPv6_1, ipv6NetworkInterface, UNICAST_IPv6_1); 885 fail(); 886 } catch (IllegalArgumentException expected) { 887 } 888 dc.close(); 889 } 890 891 public void test_joinSourceSpecific_nullSourceAddress_IPv4() throws Exception { 892 if (!supportsMulticast) { 893 return; 894 } 895 DatagramChannel dc = createReceiverChannel(); 896 try { 897 dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, null); 898 fail(); 899 } catch (NullPointerException expected) { 900 } 901 dc.close(); 902 } 903 904 public void test_joinSourceSpecific_nullSourceAddress_IPv6() throws Exception { 905 if (!supportsMulticast) { 906 return; 907 } 908 DatagramChannel dc = createReceiverChannel(); 909 try { 910 dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, null); 911 fail(); 912 } catch (NullPointerException expected) { 913 } 914 dc.close(); 915 } 916 917 public void test_joinSourceSpecific_mixedAddressTypes() throws Exception { 918 if (!supportsMulticast) { 919 return; 920 } 921 DatagramChannel dc = createReceiverChannel(); 922 try { 923 dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv6_1); 924 fail(); 925 } catch (IllegalArgumentException expected) { 926 } 927 try { 928 dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, UNICAST_IPv4_1); 929 fail(); 930 } catch (IllegalArgumentException expected) { 931 } 932 dc.close(); 933 } 934 935 public void test_joinSourceSpecific_nonUnicastSourceAddress_IPv4() throws Exception { 936 if (!supportsMulticast) { 937 return; 938 } 939 DatagramChannel dc = createReceiverChannel(); 940 try { 941 dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, BAD_MULTICAST_IPv4); 942 fail(); 943 } catch (IllegalArgumentException expected) { 944 } 945 dc.close(); 946 } 947 948 public void test_joinSourceSpecific_nonUniicastSourceAddress_IPv6() throws Exception { 949 if (!supportsMulticast) { 950 return; 951 } 952 DatagramChannel dc = createReceiverChannel(); 953 try { 954 dc.join(GOOD_MULTICAST_IPv6, ipv6NetworkInterface, BAD_MULTICAST_IPv6); 955 fail(); 956 } catch (IllegalArgumentException expected) { 957 } 958 dc.close(); 959 } 960 961 public void test_joinSourceSpecific_multipleSourceAddressLimit() throws Exception { 962 if (!supportsMulticast) { 963 return; 964 } 965 DatagramChannel dc = createReceiverChannel(); 966 for (byte i = 1; i <= 20; i++) { 967 InetAddress sourceAddress = Inet4Address.getByAddress(new byte[] { 10, 0, 0, i}); 968 try { 969 dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, sourceAddress); 970 } catch (SocketException e) { 971 // There is a limit, that's ok according to the RI docs. For this test a lower bound of 10 972 // is used, which appears to be the default linux limit. See /proc/sys/net/ipv4/igmp_max_msf 973 assertTrue(i > 10); 974 break; 975 } 976 } 977 978 dc.close(); 979 } 980 981 /** 982 * Checks that a source-specific join() works when the receiver is bound to the multicast group 983 * address 984 */ 985 public void test_joinSourceSpecific_null() throws Exception { 986 if (!supportsMulticast) { 987 return; 988 } 989 InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface); 990 check_joinSourceSpecific( 991 ipv4LocalAddress /* senderBindAddress */, 992 GOOD_MULTICAST_IPv4 /* receiverBindAddress */, 993 GOOD_MULTICAST_IPv4 /* groupAddress */, 994 UNICAST_IPv4_1 /* badSenderAddress */, 995 ipv4NetworkInterface); 996 } 997 998 /** 999 * Checks that a source-specific join() works when the receiver is bound to the multicast group 1000 * address 1001 */ 1002 public void test_joinSourceSpecific_groupBind_ipv4() throws Exception { 1003 if (!supportsMulticast) { 1004 return; 1005 } 1006 InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface); 1007 check_joinSourceSpecific( 1008 ipv4LocalAddress /* senderBindAddress */, 1009 GOOD_MULTICAST_IPv4 /* receiverBindAddress */, 1010 GOOD_MULTICAST_IPv4 /* groupAddress */, 1011 UNICAST_IPv4_1 /* badSenderAddress */, 1012 ipv4NetworkInterface); 1013 } 1014 1015 /** 1016 * Checks that a source-specific join() works when the receiver is bound to the multicast group 1017 * address 1018 */ 1019 public void test_joinSourceSpecific_groupBind_ipv6() throws Exception { 1020 if (!supportsMulticast) { 1021 return; 1022 } 1023 InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface); 1024 check_joinSourceSpecific( 1025 ipv6LocalAddress /* senderBindAddress */, 1026 GOOD_MULTICAST_IPv6 /* receiverBindAddress */, 1027 GOOD_MULTICAST_IPv6 /* groupAddress */, 1028 UNICAST_IPv6_1 /* badSenderAddress */, 1029 ipv6NetworkInterface); 1030 } 1031 1032 /** Checks that a source-specific join() works when the receiver is bound to the "any" address */ 1033 public void test_joinSourceSpecific_anyBind_ipv4() throws Exception { 1034 if (!supportsMulticast) { 1035 return; 1036 } 1037 InetAddress ipv4LocalAddress = getLocalIpv4Address(ipv4NetworkInterface); 1038 check_joinSourceSpecific( 1039 ipv4LocalAddress /* senderBindAddress */, 1040 WILDCARD_IPv4 /* receiverBindAddress */, 1041 GOOD_MULTICAST_IPv4 /* groupAddress */, 1042 UNICAST_IPv4_1 /* badSenderAddress */, 1043 ipv4NetworkInterface); 1044 } 1045 1046 /** Checks that a source-specific join() works when the receiver is bound to the "any" address */ 1047 public void test_joinSourceSpecific_anyBind_ipv6() throws Exception { 1048 if (!supportsMulticast) { 1049 return; 1050 } 1051 InetAddress ipv6LocalAddress = getLocalIpv6Address(ipv6NetworkInterface); 1052 check_joinSourceSpecific( 1053 ipv6LocalAddress /* senderBindAddress */, 1054 WILDCARD_IPv6 /* receiverBindAddress */, 1055 GOOD_MULTICAST_IPv6 /* groupAddress */, 1056 UNICAST_IPv6_1 /* badSenderAddress */, 1057 ipv6NetworkInterface); 1058 } 1059 1060 /** 1061 * Checks that the source-specific membership is correctly source-filtering. 1062 * 1063 * @param senderBindAddress the address to bind the sender socket to 1064 * @param receiverBindAddress the address to bind the receiver socket to 1065 * @param groupAddress the group address to join 1066 * @param badSenderAddress a unicast address to join to perform a negative test 1067 * @param networkInterface The network interface on which to join the multicast group 1068 */ 1069 private void check_joinSourceSpecific( 1070 InetAddress senderBindAddress, InetAddress receiverBindAddress, InetAddress groupAddress, 1071 InetAddress badSenderAddress, NetworkInterface networkInterface) 1072 throws Exception { 1073 DatagramChannel sendingChannel = DatagramChannel.open(); 1074 // In order to be source-specific the sender's address must be known. The sendingChannel is 1075 // explicitly bound to a known, non-loopback address. 1076 sendingChannel.bind(new InetSocketAddress(senderBindAddress, 0)); 1077 InetSocketAddress sendingAddress = (InetSocketAddress) sendingChannel.getLocalAddress(); 1078 1079 DatagramChannel receivingChannel = DatagramChannel.open(); 1080 receivingChannel.bind( 1081 new InetSocketAddress(receiverBindAddress, 0) /* local port left to the OS to determine */); 1082 configureChannelForReceiving(receivingChannel); 1083 1084 InetSocketAddress localReceivingAddress = 1085 (InetSocketAddress) receivingChannel.getLocalAddress(); 1086 InetSocketAddress groupSocketAddress = 1087 new InetSocketAddress(groupAddress, localReceivingAddress.getPort()); 1088 MembershipKey membershipKey1 = receivingChannel 1089 .join(groupSocketAddress.getAddress(), networkInterface, senderBindAddress); 1090 1091 ByteBuffer receiveBuffer = ByteBuffer.allocate(10); 1092 1093 // Send a message. It should be received. 1094 String msg1 = "Hello1"; 1095 sendMessage(sendingChannel, msg1, groupSocketAddress); 1096 InetSocketAddress sourceAddress1 = (InetSocketAddress) receivingChannel.receive(receiveBuffer); 1097 assertEquals(sourceAddress1, sendingAddress); 1098 assertEquals(msg1, new String(receiveBuffer.array(), 0, receiveBuffer.position())); 1099 1100 membershipKey1.drop(); 1101 1102 receivingChannel.join(groupSocketAddress.getAddress(), networkInterface, badSenderAddress); 1103 1104 // Send a message. It should not be received. 1105 String msg2 = "Hello2"; 1106 sendMessage(sendingChannel, msg2, groupSocketAddress); 1107 InetSocketAddress sourceAddress2 = (InetSocketAddress) receivingChannel.receive(receiveBuffer); 1108 assertNull(sourceAddress2); 1109 1110 receivingChannel.close(); 1111 sendingChannel.close(); 1112 } 1113 1114 public void test_dropSourceSpecific_twice_IPv4() throws Exception { 1115 check_dropSourceSpecific_twice( 1116 GOOD_MULTICAST_IPv4 /* groupAddress */, UNICAST_IPv4_1 /* sourceAddress */, 1117 ipv4NetworkInterface); 1118 } 1119 1120 public void test_dropSourceSpecific_twice_IPv6() throws Exception { 1121 check_dropSourceSpecific_twice( 1122 GOOD_MULTICAST_IPv6 /* groupAddress */, UNICAST_IPv6_1 /* sourceAddress */, 1123 ipv6NetworkInterface); 1124 } 1125 1126 private void check_dropSourceSpecific_twice(InetAddress groupAddress, InetAddress sourceAddress, 1127 NetworkInterface networkInterface) 1128 throws Exception { 1129 if (!supportsMulticast) { 1130 return; 1131 } 1132 DatagramChannel dc = createReceiverChannel(); 1133 MembershipKey membershipKey = dc.join(groupAddress, networkInterface, sourceAddress); 1134 1135 assertTrue(membershipKey.isValid()); 1136 membershipKey.drop(); 1137 assertFalse(membershipKey.isValid()); 1138 1139 // Try to leave a group we are no longer a member of - should do nothing. 1140 membershipKey.drop(); 1141 1142 dc.close(); 1143 } 1144 1145 public void test_dropSourceSpecific_sourceKeysAreIndependent_IPv4() throws Exception { 1146 check_dropSourceSpecific_sourceKeysAreIndependent( 1147 GOOD_MULTICAST_IPv4 /* groupAddress */, 1148 UNICAST_IPv4_1 /* sourceAddress1 */, 1149 UNICAST_IPv4_2 /* sourceAddress2 */, 1150 ipv4NetworkInterface); 1151 } 1152 1153 public void test_dropSourceSpecific_sourceKeysAreIndependent_IPv6() throws Exception { 1154 check_dropSourceSpecific_sourceKeysAreIndependent( 1155 GOOD_MULTICAST_IPv6 /* groupAddress */, 1156 UNICAST_IPv6_1 /* sourceAddress1 */, 1157 UNICAST_IPv6_2 /* sourceAddress2 */, 1158 ipv6NetworkInterface); 1159 } 1160 1161 private void check_dropSourceSpecific_sourceKeysAreIndependent( 1162 InetAddress groupAddress, InetAddress sourceAddress1, InetAddress sourceAddress2, 1163 NetworkInterface networkInterface) throws Exception { 1164 if (!supportsMulticast) { 1165 return; 1166 } 1167 DatagramChannel dc = createReceiverChannel(); 1168 MembershipKey membershipKey1 = dc.join(groupAddress, networkInterface, sourceAddress1); 1169 MembershipKey membershipKey2 = dc.join(groupAddress, networkInterface, sourceAddress2); 1170 assertFalse(membershipKey1.equals(membershipKey2)); 1171 assertTrue(membershipKey1.isValid()); 1172 assertTrue(membershipKey2.isValid()); 1173 1174 membershipKey1.drop(); 1175 1176 assertFalse(membershipKey1.isValid()); 1177 assertTrue(membershipKey2.isValid()); 1178 1179 dc.close(); 1180 } 1181 1182 public void test_drop_keyBehaviorAfterDrop() throws Exception { 1183 if (!supportsMulticast) { 1184 return; 1185 } 1186 DatagramChannel dc = createReceiverChannel(); 1187 MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4NetworkInterface, UNICAST_IPv4_1); 1188 membershipKey.drop(); 1189 assertFalse(membershipKey.isValid()); 1190 1191 try { 1192 membershipKey.block(UNICAST_IPv4_1); 1193 fail(); 1194 } catch (IllegalStateException expected) { 1195 } 1196 1197 try { 1198 membershipKey.unblock(UNICAST_IPv4_1); 1199 fail(); 1200 } catch (IllegalStateException expected) { 1201 } 1202 1203 assertSame(dc, membershipKey.channel()); 1204 assertSame(GOOD_MULTICAST_IPv4, membershipKey.group()); 1205 assertSame(UNICAST_IPv4_1, membershipKey.sourceAddress()); 1206 assertSame(ipv4NetworkInterface, membershipKey.networkInterface()); 1207 } 1208 1209 private static void configureChannelForReceiving(DatagramChannel receivingChannel) 1210 throws Exception { 1211 1212 // NOTE: At the time of writing setSoTimeout() has no effect in the RI, making these tests hang 1213 // if the channel is in blocking mode. configureBlocking(false) is used instead and rely on the 1214 // network to the local host being instantaneous. 1215 // receivingChannel.socket().setSoTimeout(200); 1216 // receivingChannel.configureBlocking(true); 1217 receivingChannel.configureBlocking(false); 1218 } 1219 1220 private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException { 1221 return iface.isUp() 1222 // Typically loopback interfaces do not support multicast, but they are ruled out 1223 // explicitly here anyway. 1224 && !iface.isLoopback() && iface.supportsMulticast() 1225 && iface.getInetAddresses().hasMoreElements(); 1226 } 1227 1228 private static void sendMulticastMessage( 1229 InetAddress group, int port, String msg, NetworkInterface sendingInterface) 1230 throws IOException { 1231 // Any datagram socket can send to a group. It does not need to have joined the group. 1232 DatagramChannel dc = DatagramChannel.open(); 1233 if (sendingInterface != null) { 1234 // For some reason, if set, this must be set to a real (non-loopback) device for an IPv6 1235 // group, but can be loopback for an IPv4 group. 1236 dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, sendingInterface); 1237 } 1238 sendMessage(dc, msg, new InetSocketAddress(group, port)); 1239 dc.close(); 1240 } 1241 1242 private static void sendMessage( 1243 DatagramChannel sendingChannel, String msg, InetSocketAddress targetAddress) 1244 throws IOException { 1245 1246 ByteBuffer sendBuffer = ByteBuffer.wrap(msg.getBytes()); 1247 sendingChannel.send(sendBuffer, targetAddress); 1248 } 1249 1250 private static InetAddress getLocalIpv4Address(NetworkInterface networkInterface) { 1251 for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) { 1252 if (interfaceAddress.getAddress() instanceof Inet4Address) { 1253 return interfaceAddress.getAddress(); 1254 } 1255 } 1256 throw new AssertionFailedError("Unable to find local IPv4 address for " + networkInterface); 1257 } 1258 1259 private static InetAddress getLocalIpv6Address(NetworkInterface networkInterface) { 1260 for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) { 1261 if (interfaceAddress.getAddress() instanceof Inet6Address) { 1262 return interfaceAddress.getAddress(); 1263 } 1264 } 1265 throw new AssertionFailedError("Unable to find local IPv6 address for " + networkInterface); 1266 } 1267} 1268 1269