1 /* 2 * Copyright (c) 1997, 2003, 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.io.*; 25 import java.security.*; 26 27 class Traffic 28 { 29 private InputStream in; 30 private OutputStream out; 31 32 // 33 // By default, traffic streams are predictable and what comes 34 // in is compared with what it's expected to be. 35 // 36 static private byte fixedSeed [] = { 1, 2, 3, 4}; 37 38 private SecureRandom prng; 39 private boolean compareRandom = true; 40 41 Traffic(InputStream in, OutputStream out)42 Traffic (InputStream in, OutputStream out) 43 { 44 this.in = in; 45 this.out = out; 46 try { 47 prng = SecureRandom.getInstance("SHA1PRNG"); 48 } catch (NoSuchAlgorithmException e) { 49 throw new RuntimeException(e); 50 } 51 prng.setSeed(fixedSeed); 52 } 53 54 // optionally provide PRNG for "truly" random data. setPRNG(SecureRandom prng)55 public void setPRNG (SecureRandom prng) 56 { 57 this.prng = prng; 58 compareRandom = false; 59 } 60 61 62 // 63 // Basic half-duplex testing, as used for RPC-style systems like 64 // HTTP, RMI, CORBA, ONC, etc. 65 // 66 // parameter 'n' is "0" for some fixed data tests, else is the 67 // number of passes of random data to send. 68 // 69 initiate(int n)70 public void initiate (int n) 71 throws IOException 72 { 73 // System.out.println ("Initiating N = " + n); 74 75 if (n == 0) 76 initiateConst (); 77 else if (n < 0) 78 System.out.println ("** ERROR: initiate forever ??"); 79 else 80 for ( ; n > 0; n -= 1) { 81 initiateRandom (); 82 } 83 } 84 85 respond(int n)86 public void respond (int n) 87 throws IOException 88 { 89 if (n == 0) 90 respondConst (); 91 else if (n < 0) // n < 0 == respond forever 92 while (true) 93 respondRandom (); 94 else 95 while (n-- > 0) 96 respondRandom (); 97 } 98 99 100 // 101 // Test passing of fixed size (and content) data. 102 // 103 // For SSL, one test goal is to ensure that all the basic 104 // block cipher padding sizes get banged on. SSLv3 ciphers 105 // are all the same block size, but there are larger sizes 106 // coming along. (Big blocks in hardware can be fast!!) 107 // 108 109 private static final int MAX_BLOCKSIZE = 8 * 2; 110 writeConstData(int n)111 private void writeConstData (int n) 112 throws IOException 113 { 114 if (n <= 0) 115 return; 116 117 byte buf [] = new byte [n]; 118 119 for (int i = 0; i < n; i++) 120 buf [i] = (byte) i; 121 122 out.write (buf); 123 124 /* 125 System.out.println (Thread.currentThread ().getName () 126 + " wrote const data size = " + n); 127 */ 128 } 129 readConstData(int n)130 private void readConstData (int n) 131 throws IOException 132 { 133 if (n <= 0) 134 return; 135 136 byte buf [] = new byte [n]; 137 138 in.read (buf); 139 140 for (int i = 0; i < n; i++) 141 if (buf [i] != (byte) i) 142 throw new IOException ("const data was incorrect, " 143 + "n = " + n + ", i = " + i); 144 145 /* 146 System.out.println (Thread.currentThread ().getName () 147 + " read const data size = " + n); 148 */ 149 } 150 initiateConst()151 private void initiateConst () 152 throws IOException 153 { 154 for (int i = 1; i <= MAX_BLOCKSIZE; i++) { 155 writeConstData (i); 156 readConstData (i); 157 } 158 159 } 160 respondConst()161 private void respondConst () 162 throws IOException 163 { 164 for (int i = 1; i <= MAX_BLOCKSIZE; i++) { 165 readConstData (i); 166 writeConstData (i); 167 } 168 } 169 170 171 // 172 // Test passing of random size (and content) data. 173 // 174 // For SSL, one test goal is to ensure that all the basic 175 // record sizes get banged on. Traffic will normally 176 // be bimodal (small packets, and big ones) and we give 177 // a half-hearted effort at emulating that -- no real 178 // statistics to back up this particular distribution. 179 // 180 181 private static final int MAX_RECORDSIZE = 16384 * 2; 182 nextRecordSize()183 private int nextRecordSize () 184 { 185 double d = prng.nextGaussian (); 186 int n; 187 188 // assume 1/3 traffic is "big", less variance 189 if ((prng.nextInt () % 3) == 0) { 190 n = (int) (d * 2048); 191 n += 15 * 1024; 192 193 // ... and the rest is smaller, much variance 194 } else { 195 n = (int) (d * 4096); 196 n += 1024; 197 } 198 199 if (n < 0) 200 return nextRecordSize (); 201 else if (n > MAX_RECORDSIZE) 202 return MAX_RECORDSIZE; 203 else 204 return n; 205 } 206 207 writeRandomData()208 private void writeRandomData () 209 throws IOException 210 { 211 int n = nextRecordSize (); 212 byte buf [] = new byte [n]; 213 214 // System.out.println ("write, size = " + n); 215 216 prng.nextBytes (buf); 217 218 writeInt (n); 219 out.write (buf); 220 } 221 readRandomData()222 private void readRandomData () 223 throws IOException 224 { 225 int n = readInt (); 226 byte actual [] = new byte [n]; 227 228 readFully (actual); 229 230 if (compareRandom) { 231 byte expected []; 232 233 if (n != nextRecordSize ()) 234 throw new IOException ("wrong record size"); 235 236 expected = new byte [n]; 237 prng.nextBytes (expected); 238 239 for (int i = 0; i < n; i++) 240 if (actual [i] != expected [i]) 241 throw new IOException ("random data was incorrect, " 242 + "n = " + n + ", i = " + i); 243 } 244 } 245 initiateRandom()246 private void initiateRandom () 247 throws IOException 248 { 249 writeRandomData (); 250 readRandomData (); 251 252 } 253 respondRandom()254 private void respondRandom () 255 throws IOException 256 { 257 readRandomData (); 258 writeRandomData (); 259 } 260 261 readFully(byte buf [])262 private void readFully (byte buf []) 263 throws IOException 264 { 265 int len = buf.length; 266 int offset = 0; 267 int value; 268 269 while (len > 0) { 270 value = in.read (buf, offset, len); 271 if (value == -1) 272 throw new EOFException ("read buffer"); 273 offset += value; 274 len -= value; 275 } 276 } 277 278 readInt()279 private int readInt () 280 throws IOException 281 { 282 int b0, b1, b2, b3; 283 int n; 284 285 b0 = in.read (); 286 b1 = in.read (); 287 b2 = in.read (); 288 b3 = in.read (); 289 290 if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) 291 throw new EOFException (); 292 293 /* 294 System.out.println ("READ: b0 = " + b0 + ", b1 = " + b1 295 + ", b2 = " + b2 + ", b3 = " + b3); 296 */ 297 298 n = (b3 & 0x0ff); 299 n |= (b2 & 0x0ff) << 8; 300 n |= (b1 & 0x0ff) << 16; 301 n |= (b0 & 0x0ff) << 24; 302 return n; 303 } 304 writeInt(int n)305 private void writeInt (int n) 306 throws IOException 307 { 308 int b0, b1, b2, b3; 309 310 b3 = n & 0x0ff; 311 n >>= 8; 312 b2 = n & 0x0ff; 313 n >>= 8; 314 b1 = n & 0x0ff; 315 n >>= 8; 316 b0 = n & 0x0ff; 317 318 /* 319 System.out.println ("WRITE: b0 = " + b0 + ", b1 = " + b1 320 + ", b2 = " + b2 + ", b3 = " + b3); 321 */ 322 323 out.write (b0); 324 out.write (b1); 325 out.write (b2); 326 out.write (b3); 327 } 328 } 329