1/* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 24/* @test 25 * @bug 8014499 26 * @summary Test for interference when two sockets are bound to the same 27 * port but joined to different multicast groups 28 * @run main Promiscuous 29 * @run main/othervm -Djava.net.preferIPv4Stack=true Promiscuous 30 */ 31 32import java.io.IOException; 33import static java.lang.System.out; 34import java.net.*; 35 36public class Promiscuous { 37 38 static final int TIMEOUT = 5 * 1000; // 5 secs 39 static int id = 1000; 40 41 static void receive(MulticastSocket mc, boolean datagramExpected, int id) 42 throws IOException 43 { 44 byte[] ba = new byte[100]; 45 DatagramPacket p = new DatagramPacket(ba, ba.length); 46 try { 47 mc.receive(p); 48 int recvId = Integer.parseInt( 49 new String(p.getData(), 0, p.getLength(), "UTF-8")); 50 if (datagramExpected) { 51 if (recvId != id) 52 throw new RuntimeException("Unexpected id, got " + recvId 53 + ", expected: " + id); 54 out.printf("Received message as expected, %s\n", p.getAddress()); 55 } else { 56 throw new RuntimeException("Unexpected message received, " 57 + p.getAddress()); 58 } 59 } catch (SocketTimeoutException e) { 60 if (datagramExpected) 61 throw new RuntimeException("Expected message not received, " 62 + e.getMessage()); 63 else 64 out.printf("Message not received, as expected\n"); 65 } 66 } 67 68 static void test(InetAddress group1, InetAddress group2) 69 throws IOException 70 { 71 try (MulticastSocket mc1 = new MulticastSocket(); 72 MulticastSocket mc2 = new MulticastSocket(mc1.getLocalPort()); 73 DatagramSocket ds = new DatagramSocket()) { 74 final int port = mc1.getLocalPort(); 75 out.printf("Using port: %d\n", port); 76 77 mc1.setSoTimeout(TIMEOUT); 78 mc2.setSoTimeout(TIMEOUT); 79 int nextId = id; 80 byte[] msg = Integer.toString(nextId).getBytes("UTF-8"); 81 DatagramPacket p = new DatagramPacket(msg, msg.length); 82 p.setAddress(group1); 83 p.setPort(port); 84 85 mc1.joinGroup(group1); 86 out.printf("mc1 joined the MC group: %s\n", group1); 87 mc2.joinGroup(group2); 88 out.printf("mc2 joined the MC group: %s\n", group2); 89 90 out.printf("Sending datagram to: %s/%d\n", group1, port); 91 ds.send(p); 92 93 // the packet should be received by mc1 only 94 receive(mc1, true, nextId); 95 receive(mc2, false, 0); 96 97 nextId = ++id; 98 msg = Integer.toString(nextId).getBytes("UTF-8"); 99 p = new DatagramPacket(msg, msg.length); 100 p.setAddress(group2); 101 p.setPort(port); 102 103 out.printf("Sending datagram to: %s/%d\n", group2, port); 104 ds.send(p); 105 106 // the packet should be received by mc2 only 107 receive(mc2, true, nextId); 108 receive(mc1, false, 0); 109 110 mc1.leaveGroup(group1); 111 mc2.leaveGroup(group2); 112 } 113 } 114 115 public static void main(String args[]) throws IOException { 116 String os = System.getProperty("os.name"); 117 118 // Requires IP_MULTICAST_ALL on Linux (new since 2.6.31) so skip 119 // on older kernels. Note that we skip on <= version 3 to keep the 120 // parsing simple 121 if (os.equals("Linux")) { 122 String osversion = System.getProperty("os.version"); 123 String[] vers = osversion.split("\\.", 0); 124 int major = Integer.parseInt(vers[0]); 125 if (major < 3) { 126 System.out.format("Kernel version is %s, test skipped%n", osversion); 127 return; 128 } 129 } 130 131 // multicast groups used for the test 132 InetAddress ip4Group1 = InetAddress.getByName("224.7.8.9"); 133 InetAddress ip4Group2 = InetAddress.getByName("225.4.5.6"); 134 135 test(ip4Group1, ip4Group2); 136 } 137} 138