1 /* 2 * Copyright (c) 2012, 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 import java.io.IOException; 25 import java.net.Inet6Address; 26 import java.net.InetAddress; 27 import java.net.InetSocketAddress; 28 import java.net.NetworkInterface; 29 import java.net.ProtocolFamily; 30 import java.net.StandardProtocolFamily; 31 import java.net.StandardSocketOptions; 32 import java.nio.ByteBuffer; 33 import java.nio.channels.DatagramChannel; 34 import java.nio.channels.SelectionKey; 35 import java.nio.channels.Selector; 36 import java.util.Collections; 37 import java.util.Enumeration; 38 import java.util.Map; 39 40 import sun.management.jdp.JdpException; 41 import sun.management.jdp.JdpJmxPacket; 42 import sun.management.jdp.JdpPacketReader; 43 44 public class JdpClient { 45 46 private static class PacketListener implements Runnable { 47 48 private static final int BUFFER_LENGTH = 4096; 49 private final DatagramChannel channel; 50 private static int maxPacketCount = 1; 51 private static int maxEmptyPacketCount = 10; 52 53 private void get(Map<?, ?> map, String key) 54 throws JdpException { 55 56 if (map.get(key) == null) { 57 throw new JdpException("Test failed, packet field " + key + " missed"); 58 } 59 } 60 61 private void checkFieldPresence(JdpJmxPacket p) 62 throws IOException, JdpException { 63 64 byte[] b = p.getPacketData(); 65 66 JdpPacketReader reader = new JdpPacketReader(b); 67 Map<String, String> pMap = reader.getDiscoveryDataAsMap(); 68 69 get(pMap, JdpJmxPacket.UUID_KEY); 70 get(pMap, JdpJmxPacket.MAIN_CLASS_KEY); 71 get(pMap, JdpJmxPacket.JMX_SERVICE_URL_KEY); 72 // get(pMap, JdpJmxPacket.INSTANCE_NAME_KEY); 73 get(pMap, JdpJmxPacket.PROCESS_ID_KEY); 74 get(pMap, JdpJmxPacket.BROADCAST_INTERVAL_KEY); 75 get(pMap, JdpJmxPacket.RMI_HOSTNAME_KEY); 76 } 77 78 79 PacketListener(DatagramChannel channel) { 80 this.channel = channel; 81 } 82 83 @java.lang.Override 84 public void run() { 85 try { 86 Selector sel; 87 sel = Selector.open(); 88 channel.configureBlocking(false); 89 channel.register(sel, SelectionKey.OP_READ); 90 ByteBuffer buf = ByteBuffer.allocate(1024); 91 92 int count = 1; 93 int emptyPacketsCount = 1; 94 95 try { 96 while (true) { 97 98 // Use tcpdump -U -w - -s 1400 -c 2 -vv port 7095 99 // to verify that correct packet being sent 100 sel.selectedKeys().clear(); 101 buf.rewind(); 102 103 sel.select(10 * 1000); 104 channel.receive(buf); 105 106 if (buf.position() == 0) { 107 if (JdpDoSomething.getVerbose()) { 108 System.err.println("Empty packet received"); 109 } 110 if (++emptyPacketsCount > maxEmptyPacketCount) { 111 throw new RuntimeException("Test failed, maxEmptyPacketCount reached"); 112 } 113 114 continue; 115 } 116 117 buf.flip(); 118 byte[] dgramData = new byte[buf.remaining()]; 119 buf.get(dgramData); 120 try { 121 JdpJmxPacket packet = new JdpJmxPacket(dgramData); 122 JdpDoSomething.printJdpPacket(packet); 123 checkFieldPresence(packet); 124 if (++count > maxPacketCount) { 125 break; 126 } 127 } catch (JdpException e) { 128 e.printStackTrace(); 129 throw new RuntimeException("Test failed"); 130 } 131 132 } 133 134 System.out.println("OK: Test passed"); 135 136 } finally { 137 sel.close(); 138 channel.close(); 139 } 140 } catch (IOException e) { 141 e.printStackTrace(); 142 throw new RuntimeException("Test failed"); 143 } 144 } 145 } 146 147 public static void main(String[] args) { 148 try { 149 String discoveryPort = System.getProperty("com.sun.management.jdp.port"); 150 String discoveryAddress = System.getProperty("com.sun.management.jdp.address"); 151 if (discoveryAddress == null || discoveryPort == null) { 152 System.out.println("Test failed. address and port must be specified"); 153 return; 154 } 155 156 int port = Integer.parseInt(discoveryPort); 157 InetAddress address = InetAddress.getByName(discoveryAddress); 158 159 160 ProtocolFamily family = (address instanceof Inet6Address) 161 ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; 162 163 DatagramChannel channel; 164 165 channel = DatagramChannel.open(family); 166 channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); 167 channel.bind(new InetSocketAddress(port)); 168 169 Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces(); 170 for (NetworkInterface interf : Collections.list(nets)) { 171 if (interf.supportsMulticast()) { 172 try { 173 channel.join(address, interf); 174 } catch (IOException e) { 175 // Skip not configured interfaces 176 } 177 } 178 } 179 180 PacketListener listener = new PacketListener(channel); 181 new Thread(listener, "Jdp Client").start(); 182 183 } catch (RuntimeException e) { 184 System.out.println("Test failed."); 185 } catch (Exception e) { 186 e.printStackTrace(); 187 System.out.println("Test failed. unexpected error " + e); 188 } 189 } 190 }