--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/network/network004.java Thu Dec 06 16:45:26 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,878 +0,0 @@
-/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * @test
- * @key stress
- *
- * @summary converted from VM testbase nsk/stress/network/network004.
- * VM testbase keywords: [stress, slow, nonconcurrent, quick]
- * VM testbase readme:
- * DESCRIPTION
- * This test transfers huge amount of data between 2 Java virtual machines
- * using the TCP/IP protocol, and checks if those data are transfered correctly.
- * Both client and server VMs run on the same local computer and attach TCP/IP
- * sockets to the local host, or to the loopback domain ``localhost''
- * (having IP address 127.0.0.1).
- * In this test, 128 client/server connections are established. Once a
- * connection is established, client passes a large data parcel to server,
- * and server reads that parcel and checks if it is same as expected
- * (byte-to-byte equality is desired). Then server passes (some other) parcel
- * to the client, and client reads and verifies those bytes. This ping-pong
- * game is repeated 128 times; and after that each pair of sockets checks if
- * there are no extra bytes accudentally passed through their connection.
- * Parcels lengths and contents are chosen randomly, and average
- * parcel length is 128 bytes. So totally, each pair of sockets passes ~16Kb of
- * data to each other, and thus ~32Kb of data are transfered by each sockets
- * pair. Totally, ~4Mb of data are transfered by all client/server pairs.
- * COMMENTS
- * The production Solaris_JDK_1.3-b12 Server VM intermittently crashes under
- * this test, even when client part of the test is executed with Client HS:
- * >>>> java -server network004 java
- * #
- * # HotSpot Virtual Machine Error, Unexpected Signal 10
- * # Please report this error at
- * # http://java.sun.com/cgi-bin/bugreport.cgi
- * #
- * # Error ID: 4F533F534F4C415249530E43505007D9 01
- * #
- * # Problematic Thread: prio=5 tid=0x214418 nid=0x103 runnable
- * #
- * (ErrorID == "os_solaris.cpp, 2009")
- * If the client part of the test is executed with Server HS, the
- * production Solaris_JDK_1.3-b12 Server VM intermittently fails
- * this test due to timeout:
- * >>>> time java -server network004 'java -server -showversion'
- * java version "1.3"
- * Java(TM) 2 Runtime Environment, Standard Edition (build Solaris_JDK_1.3-b12)
- * Java HotSpot(TM) Server VM (build 1.3-b12, mixed mode)
- * # Client #96: java.io.InterruptedIOException: Read timed out
- * # Client VM has crashed: exit status=97
- * # Test failed.
- * 156.0u 117.0s 7:06 63% 0+0k 0+0io 0pf+0w
- * Test was fixed:
- * added WAITTIME parameter defined timeout for TCP/IP sockets in minutes
- *
- * @library /vmTestbase
- * /test/lib
- * @run driver jdk.test.lib.FileInstaller . .
- * @build nsk.stress.network.network004
- * @run main/othervm PropertyResolvingWrapper
- * nsk.stress.network.network004
- * "${test.jdk}/bin/java ${test.vm.opts} ${test.java.opts}" 5
- */
-
-package nsk.stress.network;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.UnknownHostException;
-import java.util.Random;
-import java.util.StringTokenizer;
-
-/**
- * This test transfers huge amount of data between 2 Java virtual machines
- * using the TCP/IP protocol, and checks if those data are transfered correctly.
- * Both client and server VMs run on the same local computer and attach TCP/IP
- * sockets to the local host, or to the loopback domain ``<code>localhost</code>''
- * (having IP address <code>127.0.0.1</code>).
- * <p>
- * <p>In this test, 128 client/server connections are established. Once a
- * connection is established, client passes a large data parcel to server,
- * and server reads that parcel and checks if it is same as expected
- * (byte-to-byte equality is desired). Then server passes (some other) parcel
- * to the client, and client reads and verifies those bytes. This ping-pong
- * game is repeated 128 times; and after that each pair of sockets checks if
- * there are no extra bytes accudentally passed through their connection.
- * <p>
- * <p>Parcels lengths and contents are chosen randomly, and average
- * parcel length is 128 bytes. So totally, each pair of sockets passes ~16Kb of
- * data to each other, and thus ~32Kb of data are transfered by each sockets
- * pair. Totally, ~4Mb of data are transfered by all client/server pairs.
- */
-public class network004 {
- /**
- * Timeout for TCP/IP sockets (currently set to 1 min).
- */
- private static int SO_TIMEOUT;// = 2*60*1000;
-
- /**
- * Maximal number of connections this test should open simultaneously.
- */
- private final static int MAX_CONNECTIONS = 128;
-
- /**
- * Check few more connections to make sure that MAX_CONNECTIONS are safe.
- */
- private final static int CONNECTIONS_RESERVE = 10;
-
- /**
- * Number of parcels to be sent/recieved.
- */
- private final static int DATA_PARCELS = 128;
-
- /**
- * Maximal length of data parcel to be sent/recieved
- * (it equals to 256 bytes now).
- */
- private final static int MAX_PARCEL = 1 << 8;
-
- /**
- * Either actually display optional reports or not.
- */
- static private final boolean DEBUG_MODE = false;
-
- /**
- * How many IP sockets can we open simultaneously?
- * Check if <code>MAX_CONNECTIONS</code> connections
- * can be open simultaneously.
- */
- private static int detectOSLimitation() {
- final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE;
- ServerSocket ssoc[] = new ServerSocket[CONNECTIONS_TO_TRY];
- display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:");
- int i;
- for (i = 0; i < CONNECTIONS_TO_TRY; i++)
- try {
- ssoc[i] = new ServerSocket(0);
- display("--- Open: ssoc[" + i + "] = " + ssoc[i]);
- } catch (IOException ioe) {
- display("--- OOPS! -- failed to open connection #" + i);
- break;
- }
- display("--- Could open " +
- (i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections.");
- display("--- Closing them:");
- for (int j = 0; j < i; j++)
- try {
- ssoc[j].close();
- } catch (IOException ioe) {
- throw new Error("FATAL error while loading the test: " + ioe);
- }
- display("--- OK.");
- int safeConnections = i - CONNECTIONS_RESERVE;
- if (safeConnections < 1)
- safeConnections = 1;
- if (safeConnections < MAX_CONNECTIONS) {
- complain("------------------------- CAUTION: -------------------");
- complain("While checking the OS limitations, the test found that");
- complain("only " + i + " TCP/IP socket connections could be safely open");
- complain("simultaneously. However, possibility to open at least");
- complain("" + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE
- + " connections were expected.");
- complain("");
- complain("So, the test will check only " + safeConnections + " connection"
- + (safeConnections == 1 ? "" : "s") + " which seem");
- complain("safe to be open simultaneously.");
- complain("------------------------------------------------------");
- }
- return safeConnections;
- }
-
- //----------------------------------------------------------------//
-
- /**
- * Re-calls to the method <code>run(args[],out)</code> actually
- * performing the test. After <code>run(args[],out)</code> stops,
- * follow JDK-like convention for exit codes. I.e.: stop with
- * exit status 95 if the test has passed, or with status 97 if
- * the test has failed.
- *
- * @see #run(String[], PrintStream)
- */
- public static void main(String args[]) {
- int exitCode = run(args, System.out);
- System.exit(exitCode + 95);
- // JCK-like exit status.
- }
-
- /**
- * Parse command-line parameters stored into <code>args[]</code> array,
- * then perform the test. I.e.: start the server thread at the same VM
- * this method runs, then start the other client VM, and verify data
- * transfer through TCP/IP connection between those different virtual
- * machines.
- * <p>
- * <p>There should be 1 or 2 command-line parameters:
- * <br>
- * <code>java network004 <i>java_command</i>
- * [<i>IP-address</i> | <i>host_name</i> | localhost ]</code>
- * <br>where parameters are:
- * <br>
- * <code><i>java_command</i></code> - how to start java,
- * e.g.: ``<code>c:\jdk1.3\bin\java -classic</code>''
- * <br>
- * <code>waittime</code> - timeout for TCP/IP sockets in minutes
- * <br>
- * <code><i>IP-address</i></code> - local hots's address, or 127.0.0.1
- * <br>
- * <code><i>host_name</i></code> - local host's domain name, or the
- * keyword ``<code>localhost</code>''
- * <br>
- * <code>localhost</code> - placeholder for the IP-address 127.0.0.1
- * <p>
- * <p>Usually, <code><i>java_command</i></code> should point to the same
- * Java machine just executing this test. However, every compatible Java 2
- * implementation is appropriate.
- * <p>
- * <p>If optional parameter is ommited, the test invokes the method
- * <code>InetAddress.getLocalHost()</code> to get the domain name and
- * IP-address of the local computer.
- */
- public static int run(String args[], PrintStream out) {
- network004.out = out;
-
- //
- // Get the Internet address of the local machine.
- //
- InetAddress address = null;
- try {
- switch (args.length) {
- case 2:
- address = InetAddress.getLocalHost();
- break;
- case 3:
- address = InetAddress.getByName(args[2]);
- break;
- default:
- complain("Illegal arguments number; execute:");
- complain(" java network004 $JAVA_COMMAND " +
- "[$IP_ADDRESS | $HOST_NAME | localhost]");
- return 2; // FAILED
- }
- } catch (UnknownHostException exception) {
- complain(exception.toString());
- return 2; // FAILED
- }
- display("Host: " + address);
-
- //
- // Detect if it is safe to open MAX_CONNETIONS simultaneously:
- //
- final int CONNECTIONS = detectOSLimitation();
-
- //
- // Start the server thread on the same VM (which executes this method).
- //
- Server server[] = new Server[CONNECTIONS];
- for (int i = 0; i < CONNECTIONS; i++) {
- try {
- server[i] = new Server(address);
- } catch (Exception exception) {
- complain("Server #" + i + ": " + exception);
- return 2;
- }
- display("Server #" + i + ": " + server[i]);
- server[i].start();
- }
-
- //
- // Start the client process on different VM.
- //
- String command = args[0] + " " + network004.class.getName() + "$Client";
- try {
- SO_TIMEOUT = Integer.parseInt(args[1]) * 60 * 1000;
- } catch (NumberFormatException e) {
- complain("Wrong timeout argument: " + e);
- return 2;
- }
-
- Runtime runtime = Runtime.getRuntime();
-
- Process client = null;
- IORedirector redirectOut = null;
- IORedirector redirectErr = null;
-
- try {
- // Start clients on different JVM:
- client = runtime.exec(command);
-
- // Provide clients with access to stderr and stdout:
- InputStream clientOut = client.getInputStream();
- InputStream clientErr = client.getErrorStream();
- redirectOut = new IORedirector(clientOut, DEBUG_MODE ? out : null);
- redirectErr = new IORedirector(clientErr, out);
- redirectOut.start();
- redirectErr.start();
-
- // Pass parameters to clients (number of connections, and IP adresses and ports):
- PrintStream clientIn = new PrintStream(client.getOutputStream());
- clientIn.println(CONNECTIONS);
- for (int i = 0; i < CONNECTIONS; i++)
- clientIn.println(server[i].getIPAddress() + " " + server[i].getPort());
- clientIn.flush();
- clientIn.close();
-
- } catch (Exception exception) {
- complain("Failed to start client: " + exception);
- return 2;
- }
-
- //
- // Wait until the server and client both stop.
- //
- boolean testFailed = false;
- try {
- client.waitFor();
- // Let I/O redirectors to flush:
- if (redirectOut.isAlive())
- redirectOut.join();
- if (redirectErr.isAlive())
- redirectErr.join();
-
- // If client has crashed, also terminate the server (to avoid hangup).
- int clientStatus = client.exitValue();
- if (clientStatus != 95) {
- complain("Client VM has failed: exit status=" + clientStatus);
- testFailed = true;
- }
-
- // Client has finished OK; wait for the server.
- for (int i = 0; i < CONNECTIONS; i++) {
- display("Server: waiting for #" + i);
- while (server[i].isAlive())
- server[i].join();
- if (server[i].exception != null) {
- complain("Server thread #" + i + ": " + server[i].exception);
- testFailed = true;
- }
- }
-
- } catch (Exception exception) {
- complain("Test interrupted: " + exception);
- testFailed = true;
- }
-
- if (testFailed)
- complain("Test failed.");
- else
- display("Test passed.");
- return testFailed ? 2 : 0;
- }
-
- //----------------------------------------------------------------//
-
- /**
- * Log stream for error messages and/or (optional) execution trace.
- */
- private static PrintStream out;
-
- /**
- * Print error message.
- */
- private static synchronized void complain(Object message) {
- out.println("# " + message);
- out.flush();
- }
-
- /**
- * Display optional report: comment ca va?
- */
- private static synchronized void display(Object report) {
- if (DEBUG_MODE)
- out.println(report.toString());
- out.flush();
- }
-
- //----------------------------------------------------------------//
-
- /**
- * Server thread should reply to data parcels sent by Client VM.
- */
- private static class Server extends Thread {
- /**
- * The socket to listen for a client.
- */
- private ServerSocket serverSocket;
-
- /**
- * Display the server socket.
- */
- public String toString() {
- return serverSocket.toString();
- }
-
- /**
- * Server's IP-address in the form ``<code><i>x.y.u.z</i></code>'',
- * or ``<code>127.0.0.1</code>'' for loopback connection.
- */
- public String getIPAddress() {
- return serverSocket.getInetAddress().getHostAddress();
- }
-
- /**
- * Which port is this socket listening?
- */
- int getPort() {
- return serverSocket.getLocalPort();
- }
-
- /**
- * Find some free port at the given <code>address</code>
- * and attach new server to hear that port.
- */
- public Server(InetAddress address) throws IOException {
- int someFreePort = 0;
- int backlog = 50; // default for new ServerSocket(port)
- serverSocket = new ServerSocket(someFreePort, backlog, address);
- }
-
- /**
- * Exception just arisen while the server was working,
- * or <code>null</code> if it was OK with the server.
- */
- Exception exception = null;
-
- /**
- * Accept connection, then reply to client's parcels.
- */
- public void run() {
- try {
- Socket socket = serverSocket.accept();
- socket.setSoTimeout(SO_TIMEOUT);
-// display("Server: " + socket);
-
- InputStream istream = socket.getInputStream();
- OutputStream ostream = socket.getOutputStream();
-
- Random random = new Random(getPort());
-
- for (int i = 0; i < DATA_PARCELS; i++) {
- Parcel etalon = new Parcel(random);
-
- Parcel sample = new Parcel(istream); // read
- if (!sample.equals(etalon)) {
- complain("Server thread for port #"
- + getPort() + " got unexpected parcel:\n"
- + "sample=" + sample + "\n"
- + "etalon=" + etalon);
- throw new TestFailure(
- "server has read unexpected parcel");
- }
-
- etalon.send(ostream);
- ostream.flush();
- }
-
- int datum = istream.read(); // wait for client close()
- if (datum >= 0)
- throw new TestFailure(
- "server has read ambigous byte: " + datum);
-
- ostream.close(); // implies: socket.close();
-
- } catch (Exception oops) {
- exception = oops;
- }
- }
-
- }
-
- //----------------------------------------------------------------//
-
- /**
- * Client VM should send data parcels to Server VM and
- * recieve and verify the server's replies.
- */
- private static class Client extends Thread {
- /**
- * This thread uses the single client socket.
- */
- private Socket socket;
-
- /**
- * Address and port of this socket.
- */
- public String toString() {
- return socket.toString();
- }
-
- /**
- * Did the thread failed? If yes, what is the failure's reason.
- */
- Exception exception = null;
-
- /**
- * Connect client socket on the given <code>address</code>
- * and <code>port</code>.
- */
- Client(InetAddress address, int port) throws IOException {
- socket = new Socket(address, port);
- socket.setSoTimeout(SO_TIMEOUT);
- }
-
- /**
- * What is the port number this socket is listening for?
- */
- int getPort() {
- return socket.getPort();
- }
-
- /**
- * Establish connection, then read/respond <code>DATA_PARCELS</code> parcels
- * of random data. Set initial seed for pseudo-random numbers generator
- * to the value of the local port number.
- *
- * @see #DATA_PARCELS
- * @see #getPort()
- */
- public void run() {
- try {
- InputStream istream = socket.getInputStream();
- OutputStream ostream = socket.getOutputStream();
-
- Random random = new Random(getPort());
-
- for (int i = 0; i < DATA_PARCELS; i++) {
- Parcel etalon = new Parcel(random);
- etalon.send(ostream);
- ostream.flush();
-
- Parcel sample = new Parcel(istream); // read
- if (!sample.equals(etalon)) {
- complain("Client thread for port #"
- + getPort() + " got unexpected parcel:\n"
- + "sample=" + sample + "\n"
- + "etalon=" + etalon);
- throw new TestFailure(
- "parcel context is unexpected to client");
- }
- }
-
- if (istream.available() > 0) {
- int datum = istream.read();
- throw new TestFailure(
- "client has read ambigous byte: " + datum);
- }
- ostream.close(); // implies: socket.close()
-
- } catch (Exception oops) {
- exception = oops;
- }
- }
-
- /**
- * Establish connections to lots of server sockets, atack servers with
- * huge data parcels, and check if it replies correctly. The addresses
- * and port numbers for server sockets are passed through <code>stdin</code>.
- * The input stream must consist of the stipulated number (up to 128+1) of
- * lines containing the pair of symbolic server domain name and the port number,
- * like:
- * <br> actual_number_of_sockets
- * <br> address_1 port_1
- * <br> address_2 port_2
- * <br> . . .
- * <br> address_N port_N
- * <br>where N must equal to the actual_number_of_sockets.
- */
- public static void main(String args[]) {
- // ---- Parse stdin for the list of server sockets: ---- //
- BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
-
- final int CONNECTIONS;
- try {
- String line = in.readLine();
- if (line == null) {
- complain("Client expects paramenets passed through stdin:");
- complain(" actual_number_of_sockets");
- complain(" IP-address_1 port_1");
- complain(" IP-address_2 port_2");
- complain(" . . .");
- complain(" IP-address_N port_N");
- exit(2); // FAILED
- }
- CONNECTIONS = Integer.parseInt(line);
- } catch (IOException ioe) {
- complain("Client failed to read the actual number of CONNECTIONS");
- throw new RuntimeException(ioe.toString());
- }
-
- Client client[] = new Client[CONNECTIONS];
- for (int i = 0; i < CONNECTIONS; i++)
- try {
- String line = in.readLine();
- if (line == null) {
- complain("Client: failed to read address/port for client #" + i);
- exit(3);
- }
-
- StringTokenizer tokenz = new StringTokenizer(line);
- if (tokenz.countTokens() != 2) {
- complain("Client: illegal input string: " + line);
- exit(3);
- }
- String serverName = (String) tokenz.nextElement();
- InetAddress address = InetAddress.getByName(serverName);
- int port = Integer.parseInt((String) tokenz.nextElement());
-
- client[i] = new Client(address, port);
-
- display("Client #" + i + ": " + client[i]);
-
- } catch (IOException ioe) {
- complain("Client #" + i + ": " + ioe);
- exit(3);
- }
-
- // ---- Start testing: ---- //
-
- for (int i = 0; i < CONNECTIONS; i++)
- client[i].start();
-
- int status = 0;
- for (int i = 0; i < CONNECTIONS; i++) {
- display("Client: waiting for #" + i);
- while (client[i].isAlive())
- yield();
- if (client[i].exception != null) {
- complain("Client #" + i + ": " + client[i].exception);
- status = 2;
- }
- }
-
- exit(status);
- }
-
- /**
- * Print error message.
- */
- private static synchronized void complain(Object message) {
- System.err.println("# " + message);
- System.err.flush();
- }
-
- /**
- * Display execution trace.
- */
- private static synchronized void display(Object message) {
- if (!DEBUG_MODE)
- return;
- System.out.println(message.toString());
- System.out.flush();
- }
-
- /**
- * Exit with JCK-like status.
- */
- private static void exit(int exitCode) {
- System.exit(exitCode + 95);
- }
-
- }
-
- /**
- * Two of such threads should redirect <code>out</code> and <code>err</code>
- * streams of client VM.
- */
- private static class IORedirector extends Thread {
- /**
- * Source stream.
- */
- InputStream in;
- /**
- * Destination stream.
- */
- OutputStream out;
-
- /**
- * Redirect <code>in</code> to <code>out</code>.
- */
- public IORedirector(InputStream in, OutputStream out) {
- this.in = in;
- this.out = out;
- }
-
- /**
- * Read input stream until the EOF, and write everithing to output stream.
- * If output stream is assigned to <code>null</code>, do not print anything,
- * but read the input stream anywhere.
- */
- public void run() {
- try {
- for (; ; ) {
- int symbol = in.read();
- if (symbol < 0)
- break; // EOF
- if (out != null)
- out.write(symbol);
- }
-
- if (out != null)
- out.flush();
-
- } catch (Exception exception) {
- throw new TestFailure("IORedirector exception: " + exception);
- }
- }
- }
-
- //----------------------------------------------------------------//
-
- /**
- * A data parcel to be sent/recieved between Client VM and Server thread.
- * When data parcel is sent, first 4 bytes are transfered which encode the
- * <code>int</code> number equal to size of the parcel minus 1. I.e.: if
- * number of data bytes in the parcel's contents is <code>N</code>, then
- * the first 4 bytes encode the number <code>N-1</code>. After that, the
- * parcel's contents bytes are transered.
- */
- static class Parcel {
- private byte[] parcel;
-
- /**
- * Display all bytes as integer values from 0 to 255;
- * or return ``<tt>null</tt>'' if this Parcel is not
- * yet initialized.
- */
- public String toString() {
- if (parcel == null)
- return "null";
- String s = "{";
- for (int i = 0; i < parcel.length; i++)
- s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF);
- return s + "}";
- }
-
- /**
- * Generate new <code>parcel[]</code> array using the given
- * <code>random</code> numbers generator. Client and Server
- * threads should use identical <code>random</code> generators,
- * so that those threads could generate equal data parcels and
- * check the parcel just transfered.
- */
- public Parcel(Random random) {
- int size = random.nextInt(MAX_PARCEL) + 1;
- parcel = new byte[size];
- for (int i = 0; i < size; i++)
- parcel[i] = (byte) random.nextInt(256);
- }
-
- /**
- * Read exactly <code>size</code> bytes from the <code>istream</code>
- * if possible, or throw <code>TestFailure</code> if unexpected end of
- * <code>istream</code> occurs.
- */
- private static byte[] readBytes(int size, InputStream istream)
- throws IOException {
-
- byte data[] = new byte[size];
- for (int i = 0; i < size; i++) {
- int datum = istream.read();
- if (datum < 0)
- throw new TestFailure(
- "unexpected EOF: have read: " + i + " bytes of " + size);
- data[i] = (byte) datum;
- }
- return data;
- }
-
- /**
- * Read 4 bytes from <code>istream</code> and threat them to encode
- * size of data parcel following these 4 bytes.
- */
- private static int getSize(InputStream istream) throws IOException {
- byte data[] = readBytes(4, istream);
- int data0 = (int) data[0] & 0xFF;
- int data1 = (int) data[1] & 0xFF;
- int data2 = (int) data[2] & 0xFF;
- int data3 = (int) data[3] & 0xFF;
- int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24);
- int size = sizeWord + 1;
- if (size <= 0)
- throw new TestFailure("illegal size: " + size);
- return size;
- }
-
- /**
- * Send 4 bytes encoding actual size of the parcel just to be transfered.
- */
- private static void putSize(OutputStream ostream, int size)
- throws IOException {
-
- if (size <= 0)
- throw new TestFailure("illegal size: " + size);
-
- int sizeWord = size - 1;
- byte data[] = new byte[4];
- data[0] = (byte) sizeWord;
- data[1] = (byte) (sizeWord >> 8);
- data[2] = (byte) (sizeWord >> 16);
- data[3] = (byte) (sizeWord >> 24);
- ostream.write(data);
- }
-
- /**
- * Recieve data parcel.
- */
- public Parcel(InputStream istream) throws IOException {
- int size = getSize(istream);
- parcel = readBytes(size, istream);
- }
-
- /**
- * Send <code>this</code> data parcel.
- */
- public void send(OutputStream ostream) throws IOException {
- int size = parcel.length;
- putSize(ostream, size);
- ostream.write(parcel);
- }
-
- /**
- * Check byte-to-byte equality between <code>this</code> and the
- * <code>other</code> parcels.
- */
- public boolean equals(Parcel other) {
- if (this.parcel.length != other.parcel.length)
- return false;
- int size = parcel.length;
- for (int i = 0; i < size; i++)
- if (this.parcel[i] != other.parcel[i])
- return false;
- return true;
- }
-
- }
-
- /**
- * Server or Client may throw this exception to report the test failure.
- */
- static class TestFailure extends RuntimeException {
- /**
- * Report particular <code>purpose</code> of the test failure.
- */
- public TestFailure(String purpose) {
- super(purpose);
- }
-
- }
-
-}