1 /*
   2  * Copyright (c) 2019, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 import java.io.InputStream;
  26 import java.io.OutputStream;
  27 import java.net.ServerSocket;
  28 import java.net.InetAddress;
  29 import java.net.Socket;
  30 import java.net.SocketAddress;
  31 import java.nio.file.Paths;
  32 import java.util.ArrayList;
  33 import java.util.List;
  34 import jdk.jfr.Recording;
  35 import jdk.jfr.consumer.RecordedEvent;
  36 import jdk.jfr.consumer.RecordingFile;
  37 import jdk.test.lib.process.OutputAnalyzer;
  38 
  39 
  40 // This class is intended to run inside a container
  41 public class JfrNetwork {
  42     // use a unique hostname for container
  43     public static final String HOST_NAME = "container-unique-8221711";
  44     public static final String JFR_REPORTED_CONTAINER_HOSTNAME_TAG = "jfr_reported_container_hostname=";
  45 
  46     public static void main(String[] args) throws Exception {
  47         String event = args[0];
  48         try (ServerSocket ss = new ServerSocket()) {
  49             testNetworkInfo(ss, event);
  50         }
  51     }
  52 
  53     private static void assertTrue(boolean expr, String msg) {
  54         if (!expr) {
  55             throw new RuntimeException(msg);
  56         }
  57     }
  58 
  59     private static void testNetworkInfo(ServerSocket ss, String event) throws Exception {
  60         ServerSocketListener server = new ServerSocketListener(ss);
  61         server.start();
  62         SocketWriter writer = new SocketWriter(ss.getLocalSocketAddress());
  63 
  64         // setup and start the recording
  65         String recordingPath = event + ".jfr";
  66         log("========= Recording event: " + event);
  67         Recording r = new Recording();
  68         r.enable(event);
  69         r.setDestination(Paths.get("/", "tmp", recordingPath));
  70         r.start();
  71 
  72         // start the socker writer thread, write some data into the socket
  73         writer.start();
  74 
  75         // wait for writer thread to terminate, then for server thread, then stop recording
  76         writer.joinAndThrow();
  77         server.joinAndThrow();
  78         r.stop();
  79 
  80         // analyze the recording
  81         List<RecordedEvent> events = RecordingFile.readAllEvents(r.getDestination());
  82         events.forEach(e -> log ("event = " + e));
  83         assertTrue(!events.isEmpty(), "No recorded network events");
  84         RecordedEvent e = events.get(0);
  85         log(JFR_REPORTED_CONTAINER_HOSTNAME_TAG + e.getString("host"));
  86 
  87         // compare IP addresses
  88         boolean matchFound = false;
  89         InetAddress reportedByJfr = InetAddress.getByName(e.getString("address"));
  90         for (InetAddress ip : getLocalIp()) {
  91             if (ip.equals(reportedByJfr)) {
  92                 matchFound = true;
  93                 break;
  94             }
  95         }
  96         assertTrue(matchFound, "IP address match not found");
  97     }
  98 
  99     private static List<InetAddress> getLocalIp() throws Exception {
 100         List<InetAddress> addrs = new ArrayList<>();
 101         InetAddress localHost = InetAddress.getLocalHost();
 102         if (!localHost.isLoopbackAddress()) {
 103             addrs.add(localHost);
 104         }
 105 
 106         log("getLocalIp() returning:");
 107         for (InetAddress addr : addrs) {
 108             log(addr.getHostName());
 109             log(addr.getHostAddress());
 110         }
 111 
 112         return addrs;
 113     }
 114 
 115     private static void log(String msg) {
 116         System.out.println(msg);
 117     }
 118 
 119 
 120     private static class ServerSocketListener extends Thread {
 121         Exception exception;
 122         ServerSocket ss;
 123 
 124         ServerSocketListener(ServerSocket socket) throws Exception {
 125             ss = socket;
 126             ss.setReuseAddress(true);
 127             ss.bind(null);
 128             log("ServerSocker Local Address: " + ss.getLocalSocketAddress());
 129         }
 130 
 131         public void joinAndThrow() throws Exception {
 132             join();
 133             if (exception != null) {
 134                 throw exception;
 135             }
 136         }
 137 
 138         public void run() {
 139             try {
 140                 try (Socket s = ss.accept(); InputStream is = s.getInputStream()) {
 141                     System.out.println("ServerSocketListener: accepted socket connection: s = " + s);
 142                     is.read();
 143                     is.read();
 144                     is.read();
 145                 }
 146             } catch (Exception e) {
 147                 exception = e;
 148             }
 149         }
 150     }
 151 
 152 
 153     private static class SocketWriter extends Thread {
 154         Exception exception;
 155         private SocketAddress ssAddr;
 156 
 157         public SocketWriter(SocketAddress sa) {
 158             this.ssAddr = sa;
 159             System.out.println("SocketWriter(): sa = " + sa);
 160         }
 161 
 162         public void joinAndThrow() throws Exception {
 163             join();
 164             if (exception != null) {
 165                 throw exception;
 166             }
 167         }
 168 
 169         public void run() {
 170             try (Socket s = new Socket()) {
 171                 s.connect(ssAddr);
 172                 try (OutputStream os = s.getOutputStream()) {
 173                     os.write('A');
 174                     os.write('B');
 175                     os.write('C');
 176                 }
 177             } catch (Exception e) {
 178                 exception = e;
 179             }
 180         }
 181     }
 182 
 183 }