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 
main(String[] args)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 
assertTrue(boolean expr, String msg)53     private static void assertTrue(boolean expr, String msg) {
54         if (!expr) {
55             throw new RuntimeException(msg);
56         }
57     }
58 
testNetworkInfo(ServerSocket ss, String event)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 
getLocalIp()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 
log(String msg)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 
ServerSocketListener(ServerSocket socket)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 
joinAndThrow()131         public void joinAndThrow() throws Exception {
132             join();
133             if (exception != null) {
134                 throw exception;
135             }
136         }
137 
run()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 
SocketWriter(SocketAddress sa)157         public SocketWriter(SocketAddress sa) {
158             this.ssAddr = sa;
159             System.out.println("SocketWriter(): sa = " + sa);
160         }
161 
joinAndThrow()162         public void joinAndThrow() throws Exception {
163             join();
164             if (exception != null) {
165                 throw exception;
166             }
167         }
168 
run()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 }
184