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