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