169N/A/*
2362N/A * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/* @test
0N/A * @bug 4208804
0N/A *
0N/A * @summary Incoming connections should be subject to timeout
0N/A * @author Adrian Colley
0N/A *
5551N/A * @build TestIface TestImpl TestImpl_Stub
5551N/A * @run main/othervm/policy=security.policy/timeout=60
5551N/A * -Dsun.rmi.transport.tcp.readTimeout=5000 ReadTimeoutTest
0N/A */
0N/A
0N/A/* This test sets a very short read timeout, exports an object, and then
0N/A * connects to the port and does nothing. The server should close the
0N/A * connection after the timeout. If that doesn't happen, the test fails.
0N/A *
0N/A * A background thread does the read. The foreground waits for DELAY*4
0N/A * and then aborts. This should give sufficient margin for timing slop.
0N/A */
0N/A
0N/Aimport java.rmi.*;
0N/Aimport java.rmi.server.RMISocketFactory;
0N/Aimport java.io.*;
0N/Aimport java.net.*;
0N/A
0N/Apublic class ReadTimeoutTest
0N/A{
169N/A private static final int DELAY = 5000; // milliseconds
0N/A
0N/A public static void main(String[] args)
169N/A throws Exception
0N/A {
169N/A // Make trouble for ourselves
169N/A if (System.getSecurityManager() == null)
169N/A System.setSecurityManager(new RMISecurityManager());
169N/A
169N/A // Flaky code alert - hope this is executed before TCPTransport.<clinit>
169N/A System.setProperty("sun.rmi.transport.tcp.readTimeout", Integer.toString(DELAY));
169N/A
169N/A // Set the socket factory.
169N/A System.err.println("(installing socket factory)");
169N/A SomeFactory fac = new SomeFactory();
169N/A RMISocketFactory.setSocketFactory(fac);
0N/A
169N/A // Create remote object
169N/A TestImpl impl = new TestImpl();
0N/A
169N/A // Export and get which port.
169N/A System.err.println("(exporting remote object)");
169N/A TestIface stub = impl.export();
169N/A Socket DoS = null;
169N/A try {
169N/A int port = fac.whichPort();
0N/A
169N/A // Sanity
169N/A if (port == 0)
169N/A throw new Error("TEST FAILED: export didn't reserve a port(?)");
0N/A
169N/A // Now, connect to that port
169N/A //Thread.sleep(2000);
169N/A System.err.println("(connecting to listening port on 127.0.0.1:" +
169N/A port + ")");
169N/A DoS = new Socket("127.0.0.1", port);
169N/A InputStream stream = DoS.getInputStream();
0N/A
169N/A // Read on the socket in the background
169N/A boolean[] successful = new boolean[] { false };
169N/A (new SomeReader(stream, successful)).start();
0N/A
169N/A // Wait for completion
169N/A int nretries = 4;
169N/A while (nretries-- > 0) {
169N/A if (successful[0])
169N/A break;
169N/A Thread.sleep(DELAY);
169N/A }
0N/A
169N/A if (successful[0]) {
169N/A System.err.println("TEST PASSED.");
169N/A } else {
169N/A throw new Error("TEST FAILED.");
169N/A }
0N/A
169N/A } finally {
169N/A try {
169N/A if (DoS != null)
169N/A DoS.close(); // aborts the reader if still blocked
169N/A impl.unexport();
169N/A } catch (Throwable unmatter) {
169N/A }
169N/A }
0N/A
169N/A // Should exit here
0N/A }
0N/A
0N/A private static class SomeFactory
169N/A extends RMISocketFactory
0N/A {
169N/A private int servport = 0;
0N/A
169N/A public Socket createSocket(String h, int p)
169N/A throws IOException
169N/A {
169N/A return (new Socket(h, p));
169N/A }
0N/A
169N/A /** Create a server socket and remember which port it's on.
169N/A * Aborts if createServerSocket(0) is called twice, because then
169N/A * it doesn't know whether to remember the first or second port.
169N/A */
169N/A public ServerSocket createServerSocket(int p)
169N/A throws IOException
169N/A {
169N/A ServerSocket ss;
169N/A ss = new ServerSocket(p);
169N/A if (p == 0) {
169N/A if (servport != 0) {
169N/A System.err.println("TEST FAILED: " +
169N/A "Duplicate createServerSocket(0)");
169N/A throw new Error("Test aborted (createServerSocket)");
169N/A }
169N/A servport = ss.getLocalPort();
169N/A }
169N/A return (ss);
169N/A }
0N/A
169N/A /** Return which port was reserved by createServerSocket(0).
169N/A * If the return value was 0, createServerSocket(0) wasn't called.
169N/A */
169N/A public int whichPort() {
169N/A return (servport);
169N/A }
0N/A } // end class SomeFactory
0N/A
0N/A protected static class SomeReader extends Thread {
169N/A private InputStream readon;
169N/A private boolean[] vec;
0N/A
169N/A public SomeReader(InputStream s, boolean[] successvec) {
169N/A super();
169N/A this.setDaemon(true);
169N/A this.readon = s;
169N/A this.vec = successvec;
169N/A }
0N/A
169N/A public void run() {
169N/A try {
169N/A int c = this.readon.read();
169N/A if (c != -1)
169N/A throw new Error ("Server returned " + c);
169N/A this.vec[0] = true;
0N/A
169N/A } catch (IOException e) {
169N/A e.printStackTrace();
169N/A }
169N/A }
0N/A } // end class SomeReader
0N/A}