Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/net/URLConnection/DisconnectAfterEOF.java
38812 views
1
/*
2
* Copyright (c) 2002, 2010, 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
/**
25
* @test
26
* @bug 4774503
27
* @summary Calling HttpURLConnection's disconnect method after the
28
* response has been received causes havoc with persistent
29
* connections.
30
*/
31
import java.net.*;
32
import java.io.*;
33
import java.util.*;
34
35
public class DisconnectAfterEOF {
36
37
/*
38
* Worker thread to service single connection - can service
39
* multiple http requests on same connection.
40
*/
41
static class Worker extends Thread {
42
Socket s;
43
44
Worker(Socket s) {
45
this.s = s;
46
}
47
48
public void run() {
49
try {
50
InputStream in = s.getInputStream();
51
PrintStream out = new PrintStream(
52
new BufferedOutputStream(
53
s.getOutputStream() ));
54
byte b[] = new byte[1024];
55
int n = -1;
56
int cl = -1;
57
int remaining = -1;
58
StringBuffer sb = new StringBuffer();
59
boolean close = false;
60
61
boolean inBody = false;
62
for (;;) {
63
boolean sendResponse = false;
64
65
try {
66
n = in.read(b);
67
} catch (IOException ioe) {
68
n = -1;
69
}
70
if (n <= 0) {
71
if (inBody) {
72
System.err.println("ERROR: Client closed before before " +
73
"entire request received.");
74
}
75
return;
76
}
77
78
// reading entity-body
79
if (inBody) {
80
if (n > remaining) {
81
System.err.println("Receiving more than expected!!!");
82
return;
83
}
84
remaining -= n;
85
86
if (remaining == 0) {
87
sendResponse = true;
88
n = 0;
89
} else {
90
continue;
91
}
92
}
93
94
// reading headers
95
for (int i=0; i<n; i++) {
96
char c = (char)b[i];
97
98
if (c != '\n') {
99
sb.append(c);
100
continue;
101
}
102
103
104
// Got end-of-line
105
int len = sb.length();
106
if (len > 0) {
107
if (sb.charAt(len-1) != '\r') {
108
System.err.println("Unexpected CR in header!!");
109
return;
110
}
111
}
112
sb.setLength(len-1);
113
114
// empty line
115
if (sb.length() == 0) {
116
if (cl < 0) {
117
System.err.println("Content-Length not found!!!");
118
return;
119
}
120
121
// the surplus is body data
122
int dataRead = n - (i+1);
123
remaining = cl - dataRead;
124
if (remaining > 0) {
125
inBody = true;
126
break;
127
} else {
128
// entire body has been read
129
sendResponse = true;
130
}
131
} else {
132
// non-empty line - check for Content-Length
133
String line = sb.toString().toLowerCase();
134
if (line.startsWith("content-length")) {
135
StringTokenizer st = new StringTokenizer(line, ":");
136
st.nextToken();
137
cl = Integer.parseInt(st.nextToken().trim());
138
}
139
if (line.startsWith("connection")) {
140
StringTokenizer st = new StringTokenizer(line, ":");
141
st.nextToken();
142
if (st.nextToken().trim().equals("close")) {
143
close =true;
144
}
145
}
146
}
147
sb = new StringBuffer();
148
}
149
150
151
if (sendResponse) {
152
// send a large response
153
int rspLen = 32000;
154
155
out.print("HTTP/1.1 200 OK\r\n");
156
out.print("Content-Length: " + rspLen + "\r\n");
157
out.print("\r\n");
158
159
if (rspLen > 0)
160
out.write(new byte[rspLen]);
161
162
out.flush();
163
164
if (close)
165
return;
166
167
sendResponse = false;
168
inBody = false;
169
cl = -1;
170
}
171
}
172
173
} catch (IOException ioe) {
174
} finally {
175
try {
176
s.close();
177
} catch (Exception e) { }
178
System.out.println("+ Worker thread shutdown.");
179
}
180
}
181
}
182
183
/*
184
* Server thread to accept connection and create worker threads
185
* to service each connection.
186
*/
187
static class Server extends Thread {
188
ServerSocket ss;
189
190
Server(ServerSocket ss) {
191
this.ss = ss;
192
}
193
194
public void run() {
195
try {
196
for (;;) {
197
Socket s = ss.accept();
198
Worker w = new Worker(s);
199
w.start();
200
}
201
202
} catch (IOException ioe) {
203
}
204
205
System.out.println("+ Server shutdown.");
206
}
207
208
public void shutdown() {
209
try {
210
ss.close();
211
} catch (IOException ioe) { }
212
}
213
}
214
215
static URLConnection doRequest(String uri) throws IOException {
216
URLConnection uc = (new URL(uri)).openConnection();
217
uc.setDoOutput(true);
218
OutputStream out = uc.getOutputStream();
219
out.write(new byte[16000]);
220
221
// force the request to be sent
222
uc.getInputStream();
223
return uc;
224
}
225
226
static URLConnection doResponse(URLConnection uc) throws IOException {
227
int cl = ((HttpURLConnection)uc).getContentLength();
228
byte b[] = new byte[4096];
229
int n;
230
do {
231
n = uc.getInputStream().read(b);
232
if (n > 0) cl -= n;
233
} while (n > 0);
234
if (cl != 0) {
235
throw new RuntimeException("ERROR: content-length mismatch");
236
}
237
return uc;
238
}
239
240
public static void main(String args[]) throws Exception {
241
// start server
242
ServerSocket ss = new ServerSocket(0);
243
Server svr = new Server(ss);
244
svr.start();
245
246
String uri = "http://localhost:" +
247
Integer.toString(ss.getLocalPort()) +
248
"/foo.html";
249
250
/*
251
* The following is the test scenario we create here :-
252
*
253
* 1. We do a http request/response and read the response
254
* to EOF. As it's a persistent connection the idle
255
* connection should go into the keep-alive cache for a
256
* few seconds.
257
*
258
* 2. We start a second request but don't read the response.
259
* As the request is to the same server we can assume it
260
* (for our implementation anyway) that it will use the
261
* same TCP connection.
262
*
263
* 3. We "disconnect" the first HttpURLConnection. This
264
* should be no-op because the connection is in use
265
* but another request. However with 1.3.1 and 1.4/1.4.1
266
* this causes the TCP connection for the second request
267
* to be closed.
268
*
269
*/
270
URLConnection uc1 = doRequest(uri);
271
doResponse(uc1);
272
273
Thread.sleep(2000);
274
275
URLConnection uc2 = doRequest(uri);
276
277
((HttpURLConnection)uc1).disconnect();
278
279
IOException ioe = null;
280
try {
281
doResponse(uc2);
282
} catch (IOException x) {
283
ioe = x;
284
}
285
286
((HttpURLConnection)uc2).disconnect();
287
288
/*
289
* Shutdown server as we are done. Worker threads created
290
* by the server will shutdown automatically when the
291
* client connection closes.
292
*/
293
svr.shutdown();
294
295
if (ioe != null) {
296
throw ioe;
297
}
298
}
299
}
300
301