blob: 4ae35ac8ec8eafe93a9c03a3094c78e91ce5935d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/* @test
25 * @bug 4203167
26 *
27 * @summary RMI blocks in HttpAwareServerSocket.accept() if you telnet to it
28 * @author Adrian Colley
29 *
30 * @library ../../../../../java/rmi/testlibrary/
31 * @build TestIface
32 * @build TestImpl
33 * @build TestImpl_Stub
34 * @build BlockAcceptTest
35 * @run main/othervm/policy=security.policy/timeout=60 BlockAcceptTest
36 */
37
38/* This test attempts to stymie the RMI accept loop. The accept loop in
39 * RMI endlessly accepts a connection, spawns a thread for it, and repeats.
40 * The accept() call can be replaced by a user-supplied library which
41 * might foolishly block indefinitely in its accept() method, which would
42 * prevent RMI from accepting other connections on that socket.
43 *
44 * Unfortunately, HttpAwareServerSocket (default server socket) is/was such
45 * a foolish thing. It reads 4 bytes to see if they're "POST" before
46 * returning. The bug fix is to move the HTTP stuff into the mainloop,
47 * which has the side effect of enabling it for non-default socketfactories.
48 *
49 * This test:
50 * 1. Creates an object and exports it.
51 * 2. Connects to the listening RMI port and sends nothing, to hold it up.
52 * 3. Makes a regular call, using HTTP tunnelling.
53 * 4. Fails to deadlock, thereby passing the test.
54 *
55 * Some runtime dependencies I'm trying to eliminate:
56 * 1. We don't know the port number until after exporting the object, but
57 * have to set it in http.proxyPort somehow. Hopefully http.proxyPort
58 * isn't read too soon or this test will fail with a ConnectException.
59 */
60
61import java.rmi.*;
62import java.rmi.server.RMISocketFactory;
63import java.io.*;
64import java.net.*;
65
66import sun.rmi.transport.proxy.RMIMasterSocketFactory;
67import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory;
68
69public class BlockAcceptTest
70{
71 public static void main(String[] args)
72 throws Exception
73 {
74 // Make trouble for ourselves
75 if (System.getSecurityManager() == null)
76 System.setSecurityManager(new RMISecurityManager());
77
78 // HTTP direct to the server port
79 System.setProperty("http.proxyHost", "127.0.0.1");
80
81 // Set the socket factory.
82 System.err.println("(installing HTTP-out socket factory)");
83 HttpOutFactory fac = new HttpOutFactory();
84 RMISocketFactory.setSocketFactory(fac);
85
86 // Create remote object
87 TestImpl impl = new TestImpl();
88
89 // Export and get which port.
90 System.err.println("(exporting remote object)");
91 TestIface stub = impl.export();
92 try {
93 int port = fac.whichPort();
94
95 // Sanity
96 if (port == 0)
97 throw new Error("TEST FAILED: export didn't reserve a port(?)");
98
99 // Set the HTTP port, at last.
100 System.setProperty("http.proxyPort", port+"");
101
102 // Now, connect to that port
103 //Thread.sleep(2000);
104 System.err.println("(connecting to listening port on 127.0.0.1:" +
105 port + ")");
106 Socket DoS = new Socket("127.0.0.1", port);
107 // we hold the connection open until done with the test.
108
109 // The test itself: make a remote call and see if it's blocked or
110 // if it works
111 //Thread.sleep(2000);
112 System.err.println("(making RMI-through-HTTP call)");
113 System.err.println("(typical test failure deadlocks here)");
114 String result = stub.testCall("dummy load");
115
116 System.err.println(" => " + result);
117 if (!("OK".equals(result)))
118 throw new Error("TEST FAILED: result not OK");
119 System.err.println("Test passed.");
120
121 // Clean up, including writing a byte to that connection just in
122 // case an optimizer thought of optimizing it out of existence
123 try {
124 DoS.getOutputStream().write(0);
125 DoS.getOutputStream().close();
126 } catch (Throwable apathy) {
127 }
128
129 } finally {
130 try {
131 impl.unexport();
132 } catch (Throwable unmatter) {
133 }
134 }
135
136 // Should exit here
137 }
138
139 private static class HttpOutFactory
140 extends RMISocketFactory
141 {
142 private int servport = 0;
143
144 public Socket createSocket(String h, int p)
145 throws IOException
146 {
147 return ((new RMIHttpToPortSocketFactory()).createSocket(h, p));
148 }
149
150 /** Create a server socket and remember which port it's on.
151 * Aborts if createServerSocket(0) is called twice, because then
152 * it doesn't know whether to remember the first or second port.
153 */
154 public ServerSocket createServerSocket(int p)
155 throws IOException
156 {
157 ServerSocket ss;
158 ss = (new RMIMasterSocketFactory()).createServerSocket(p);
159 if (p == 0) {
160 if (servport != 0) {
161 System.err.println("TEST FAILED: " +
162 "Duplicate createServerSocket(0)");
163 throw new Error("Test aborted (createServerSocket)");
164 }
165 servport = ss.getLocalPort();
166 }
167 return (ss);
168 }
169
170 /** Return which port was reserved by createServerSocket(0).
171 * If the return value was 0, createServerSocket(0) wasn't called.
172 */
173 public int whichPort() {
174 return (servport);
175 }
176 } // end class HttpOutFactory
177}