1 /*
   2  * Copyright (c) 2003, 2016, 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.net.*;
  25 import java.io.*;
  26 import java.util.*;
  27 
  28 public class Tests {
  29 
  30     static final boolean isWindows =
  31             System.getProperty("os.name").startsWith("Windows");
  32     static final boolean isMacOS =
  33             System.getProperty("os.name", "unknown").contains("OS X");
  34 
  35     /**
  36      * performs a simple exchange of data between the two sockets
  37      * and throws an exception if there is any problem.
  38      */
  39     public static void simpleDataExchange (Socket s1, Socket s2)
  40         throws Exception {
  41 
  42         InputStream i1 = s1.getInputStream();
  43         InputStream i2 = s2.getInputStream();
  44         OutputStream o1 = s1.getOutputStream();
  45         OutputStream o2 = s2.getOutputStream();
  46 
  47         startSimpleWriter("SimpleWriter-1", o1, 100);
  48         startSimpleWriter("SimpleWriter-2", o2, 200);
  49         simpleRead (i2, 100);
  50         simpleRead (i1, 200);
  51     }
  52 
  53     static void startSimpleWriter(String threadName, final OutputStream os, final int start) {
  54         (new Thread(new Runnable() {
  55             public void run() {
  56                 try { simpleWrite(os, start); }
  57                 catch (Exception e) {unexpected(e); }
  58             }}, threadName)).start();
  59     }
  60 
  61     static void unexpected(Exception e ) {
  62         System.out.println("Unexcepted Exception: " + e);
  63         e.printStackTrace();
  64     }
  65 
  66     /**
  67      * Send a packet from s1 to s2 (ia2/s2.localPort) and check it
  68      * Send a packet from s2 to s1 (ia1/s1.localPort) and check it
  69      */
  70     public static void simpleDataExchange (DatagramSocket s1, InetAddress ia1,
  71                                            DatagramSocket s2, InetAddress ia2)
  72         throws Exception {
  73 
  74         SocketAddress dest1 = new InetSocketAddress (ia1, s1.getLocalPort());
  75         dprintln ("dest1 = " + dest1);
  76         SocketAddress dest2 = new InetSocketAddress (ia2, s2.getLocalPort());
  77         dprintln ("dest2 = " + dest2);
  78 
  79         byte[] ba = "Hello world".getBytes();
  80         byte[] bb = "HELLO WORLD1".getBytes();
  81         DatagramPacket p1 = new DatagramPacket (ba, ba.length, dest1);
  82         DatagramPacket p2 = new DatagramPacket (ba, ba.length, dest2);
  83 
  84         DatagramPacket r1 = new DatagramPacket (new byte[256], 256);
  85         DatagramPacket r2 = new DatagramPacket (new byte[256], 256);
  86 
  87         s2.send (p1);
  88         s1.send (p2);
  89         s1.receive (r1);
  90         s2.receive (r2);
  91         comparePackets (p1, r1);
  92         comparePackets (p2, r2);
  93     }
  94 
  95     /**
  96      * Send a packet from s1 to s2 (ia2/s2.localPort) and send same packet
  97      * back from s2 to sender. Check s1 receives original packet
  98      */
  99 
 100     public static void datagramEcho (DatagramSocket s1, DatagramSocket s2,
 101                                      InetAddress ia2)
 102         throws Exception {
 103 
 104         byte[] ba = "Hello world".getBytes();
 105         DatagramPacket p1;
 106 
 107         SocketAddress dest2 = null;
 108         if (ia2 != null) {
 109             dest2 = new InetSocketAddress (ia2, s2.getLocalPort());
 110             p1 = new DatagramPacket (ba, ba.length, dest2);
 111         } else {
 112             p1 = new DatagramPacket (ba, ba.length);
 113         }
 114 
 115         dprintln ("dest2 = " + dest2);
 116 
 117 
 118         DatagramPacket r1 = new DatagramPacket (new byte[256], 256);
 119         DatagramPacket r2 = new DatagramPacket (new byte[256], 256);
 120 
 121         s1.send (p1);
 122         s2.receive (r1);
 123         s2.send (r1);
 124         s1.receive (r2);
 125         comparePackets (p1, r1);
 126         comparePackets (p1, r2);
 127     }
 128 
 129     public static void comparePackets (DatagramPacket p1, DatagramPacket p2)
 130         throws Exception {
 131 
 132         byte[] b1 = p1.getData();
 133         byte[] b2 = p2.getData();
 134         int len = p1.getLength () > p2.getLength() ? p2.getLength()
 135                                                    : p1.getLength();
 136         for (int i=0; i<len; i++) {
 137             if (b1[i] != b2[i]) {
 138                 throw new Exception ("packets not the same");
 139             }
 140         }
 141     }
 142 
 143     /* check the time got is within 50% of the time expected */
 144     public static void checkTime (long got, long expected) {
 145         checkTime(got, expected, expected);
 146     }
 147 
 148     /* check the time got is between start and end, given 50% tolerance */
 149     public static void checkTime(long got, long start, long end) {
 150         dprintln("checkTime: got = " + got + " start = " + start + " end = " + end);
 151         long upper = end + (end / 2);
 152         long lower = start - (start / 2);
 153         if (got > upper || got < lower) {
 154             throw new RuntimeException("checkTime failed: got " + got
 155                     + ", expected between " + start + " and " + end);
 156         }
 157     }
 158 
 159     static boolean debug = false;
 160 
 161     public static void checkDebug (String[] args) {
 162         debug = args.length > 0 && args[0].equals("-d");
 163     }
 164 
 165     public static void dprint (String s) {
 166         if (debug) {
 167             System.out.print (s);
 168         }
 169     }
 170 
 171     public static void dprintln (String s) {
 172         if (debug) {
 173             System.out.println (s);
 174         }
 175     }
 176 
 177     static int numberInterfaces () {
 178         try {
 179             Enumeration ifs = NetworkInterface.getNetworkInterfaces();
 180             int nifs=0;
 181             while (ifs.hasMoreElements()) {
 182                 nifs++;
 183                 ifs.nextElement();
 184             }
 185             return nifs;
 186         } catch (SocketException e) {
 187             return 0;
 188         }
 189     }
 190 
 191     public static Enumeration ipv4Addresses() {
 192         return new AddrEnum (Inet4Address.class);
 193     }
 194 
 195     public static Inet4Address getFirstLocalIPv4Address () {
 196         Enumeration e = ipv4Addresses();
 197         if (!e.hasMoreElements()) {
 198             return null;
 199         }
 200         return (Inet4Address)e.nextElement();
 201     }
 202 
 203     public static Inet6Address getFirstLocalIPv6Address () {
 204         Enumeration e = ipv6Addresses();
 205         if (!e.hasMoreElements()) {
 206             return null;
 207         }
 208         return (Inet6Address)e.nextElement();
 209     }
 210 
 211     public static Enumeration ipv6Addresses() {
 212         return new AddrEnum (Inet6Address.class);
 213     }
 214 
 215     /* enumerates the Inet4Addresses or Inet6Addresses on the system */
 216 
 217     private static class AddrEnum implements Enumeration {
 218 
 219         Enumeration ifs;
 220         NetworkInterface currIf = null;
 221         InetAddress nextAddr=null;
 222         Enumeration addrs=null;
 223         Class filter;
 224 
 225         static final byte[] fe80_loopback = new byte [] {
 226             (byte)0xfe,(byte)0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,1
 227         };
 228 
 229         AddrEnum (Class filter) {
 230             this.filter = filter;
 231             try {
 232                 ifs = NetworkInterface.getNetworkInterfaces();
 233             } catch (SocketException e) {}
 234         }
 235 
 236         public boolean hasMoreElements () {
 237             if (nextAddr == null) {
 238                 nextAddr = getNext();
 239             }
 240             return (nextAddr != null);
 241         }
 242 
 243         public Object nextElement () {
 244             if (!hasMoreElements()) {
 245                 throw new NoSuchElementException ("no more addresses");
 246             }
 247             Object next = nextAddr;
 248             nextAddr = null;
 249             return next;
 250         }
 251 
 252         private InetAddress getNext() {
 253             while (true) {
 254                 if (currIf == null) {
 255                     currIf = getNextIf();
 256                     if (currIf == null) {
 257                         return null;
 258                     }
 259                     addrs = currIf.getInetAddresses();
 260                 }
 261                 while (addrs.hasMoreElements()) {
 262                     InetAddress addr = (InetAddress) addrs.nextElement();
 263                     if (filter.isInstance (addr) && !addr.isLoopbackAddress()
 264                             && !addr.isAnyLocalAddress()) {
 265                         if (Arrays.equals (addr.getAddress(), fe80_loopback)) {
 266                             continue;
 267                         }
 268                         return addr;
 269                     }
 270                 }
 271                 currIf = null;
 272             }
 273         }
 274 
 275         private NetworkInterface getNextIf () {
 276             if (ifs != null) {
 277                 while (ifs.hasMoreElements()) {
 278                     NetworkInterface nic = (NetworkInterface)ifs.nextElement();
 279                     // Skip (Windows)Teredo Tunneling Pseudo-Interface
 280                     if (isWindows) {
 281                         String dName = nic.getDisplayName();
 282                         if (dName != null && dName.contains("Teredo"))
 283                             continue;
 284                     } else if (isMacOS && nic.getName().contains("awdl")) {
 285                         continue;
 286                     }
 287                     try {
 288                         if (nic.isUp() && !nic.isLoopback())
 289                             return nic;
 290                     } catch (SocketException e) {
 291                         // ignore
 292                     }
 293                 }
 294             }
 295 
 296             return null;
 297         }
 298     }
 299 
 300     /**
 301      * Throws a RuntimeException if the boolean condition is false
 302      */
 303     public static void t_assert (boolean assertion) {
 304         if (assertion) {
 305             return;
 306         }
 307         Throwable t = new Throwable();
 308         StackTraceElement[] strace = t.getStackTrace();
 309         String msg = "Assertion failed at: " + strace[1].toString();
 310         throw new RuntimeException (msg);
 311     }
 312 
 313     private static void simpleRead (InputStream is, int start) throws Exception {
 314         byte b[] = new byte [2];
 315         for (int i=start; i<start+100; i++) {
 316             int x = is.read (b);
 317             if (x == 1) {
 318                 x += is.read (b,1,1);
 319             }
 320             if (x!=2) {
 321                 throw new Exception ("read error");
 322             }
 323             int r = bytes (b[0], b[1]);
 324             if (r != i) {
 325                 throw new Exception ("read " + r + " expected " +i);
 326             }
 327         }
 328     }
 329 
 330     /* convert signed bytes to unisigned int */
 331     private static int bytes (byte b1, byte b2) {
 332         int i1 = (int)b1 & 0xFF;
 333         int i2 = (int)b2 & 0xFF;
 334         return i1 * 256 + i2;
 335     }
 336 
 337     static void simpleWrite (OutputStream os, int start) throws Exception {
 338         byte b[] = new byte [2];
 339         for (int i=start; i<start+100; i++) {
 340             b[0] = (byte) (i / 256);
 341             b[1] = (byte) (i % 256);
 342             os.write (b);
 343         }
 344     }
 345 
 346     private static class Runner extends Thread {
 347         Runnable runnee;
 348         long delay;
 349 
 350         Runner (Runnable runnee, long delay) {
 351             super();
 352             this.runnee = runnee;
 353             this.delay = delay;
 354         }
 355 
 356         public void run () {
 357             try {
 358                 Thread.sleep (delay);
 359                 runnee.run ();
 360             } catch (Exception e) {
 361                 e.printStackTrace();
 362             }
 363         }
 364     }
 365 
 366     /*
 367      * Take the given Runnable and run it in a spawned thread
 368      * after the given time has elapsed. runAfter() returns immediately
 369      */
 370     public static void runAfter (long millis, Runnable runnee) {
 371         Runner runner = new Runner (runnee, millis);
 372         runner.start ();
 373     }
 374 
 375     static String osname;
 376 
 377     static {
 378         osname = System.getProperty ("os.name");
 379     }
 380 
 381     static boolean isLinux () {
 382         return osname.equals ("Linux");
 383     }
 384 
 385     static boolean isWindows () {
 386         return osname.startsWith ("Windows");
 387     }
 388 }