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.Socket;
  29 import java.net.SocketAddress;
  30 import java.nio.file.Paths;
  31 import java.util.List;
  32 import jdk.jfr.Recording;
  33 import jdk.jfr.consumer.RecordedEvent;
  34 import jdk.jfr.consumer.RecordingFile;
  35 import com.oracle.java.testlibrary.OutputAnalyzer;
  36 
  37 
  38 // This class is intended to run inside a container
  39 public class JfrNetwork {
  40     // use a unique hostname for container
  41     public static final String HOST_NAME = "container-unique-8221711";
  42     public static final String JFR_REPORTED_CONTAINER_HOSTNAME_TAG = "jfr_reported_container_hostname=";
  43 
  44     public static void main(String[] args) throws Exception {
  45         String event = args[0];
  46         try (ServerSocket ss = new ServerSocket()) {
  47             testNetworkInfo(ss, event);
  48         }
  49     }
  50 
  51     private static void assertTrue(boolean expr, String msg) {
  52         if (!expr) {
  53             throw new RuntimeException(msg);
  54         }
  55     }
  56 
  57     private static void testNetworkInfo(ServerSocket ss, String event) throws Exception {
  58         ServerSocketListener server = new ServerSocketListener(ss);
  59         server.start();
  60         SocketWriter writer = new SocketWriter(ss.getLocalSocketAddress());
  61 
  62         // setup and start the recording
  63         String recordingPath = event + ".jfr";
  64         log("========= Recording event: " + event);
  65         Recording r = new Recording();
  66         r.enable(event);
  67         r.setDestination(Paths.get("/", "tmp", recordingPath));
  68         r.start();
  69 
  70         // start the socker writer thread, write some data into the socket
  71         writer.start();
  72 
  73         // wait for writer thread to terminate, then for server thread, then stop recording
  74         writer.joinAndThrow();
  75         server.joinAndThrow();
  76         r.stop();
  77 
  78         // analyze the recording
  79         List<RecordedEvent> events = RecordingFile.readAllEvents(r.getDestination());
  80         events.forEach(e -> log ("event = " + e));
  81         assertTrue(!events.isEmpty(), "No recorded network events");
  82         RecordedEvent e = events.get(0);
  83         log(JFR_REPORTED_CONTAINER_HOSTNAME_TAG + e.getString("host"));
  84         verifyIpAddress(e.getString("address"));
  85     }
  86 
  87     private static void verifyIpAddress(String eventIp) throws Exception {
  88         ProcessBuilder pb = new ProcessBuilder("hostname", "--ip-address");
  89         OutputAnalyzer out = new OutputAnalyzer(pb.start());
  90         out.shouldHaveExitValue(0);
  91         log("hostname --ip-address returned: " + out.getOutput());
  92         out.shouldContain(eventIp);
  93     }
  94 
  95     private static void log(String msg) {
  96         System.out.println(msg);
  97     }
  98 
  99 
 100     private static class ServerSocketListener extends Thread {
 101         Exception exception;
 102         ServerSocket ss;
 103 
 104         ServerSocketListener(ServerSocket socket) throws Exception {
 105             ss = socket;
 106             ss.setReuseAddress(true);
 107             ss.bind(null);
 108             log("ServerSocker Local Address: " + ss.getLocalSocketAddress());
 109         }
 110 
 111         public void joinAndThrow() throws Exception {
 112             join();
 113             if (exception != null) {
 114                 throw exception;
 115             }
 116         }
 117 
 118         public void run() {
 119             try {
 120                 try (Socket s = ss.accept(); InputStream is = s.getInputStream()) {
 121                     System.out.println("ServerSocketListener: accepted socket connection: s = " + s);
 122                     is.read();
 123                     is.read();
 124                     is.read();
 125                 }
 126             } catch (Exception e) {
 127                 exception = e;
 128             }
 129         }
 130     }
 131 
 132 
 133     private static class SocketWriter extends Thread {
 134         Exception exception;
 135         private SocketAddress ssAddr;
 136 
 137         public SocketWriter(SocketAddress sa) {
 138             this.ssAddr = sa;
 139             System.out.println("SocketWriter(): sa = " + sa);
 140         }
 141 
 142         public void joinAndThrow() throws Exception {
 143             join();
 144             if (exception != null) {
 145                 throw exception;
 146             }
 147         }
 148 
 149         public void run() {
 150             try (Socket s = new Socket()) {
 151                 s.connect(ssAddr);
 152                 try (OutputStream os = s.getOutputStream()) {
 153                     os.write('A');
 154                     os.write('B');
 155                     os.write('C');
 156                 }
 157             } catch (Exception e) {
 158                 exception = e;
 159             }
 160         }
 161     }
 162 
 163 }