Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java
66646 views
1
/*
2
* Copyright (c) 2005, 2021, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.net.httpserver;
27
28
import java.nio.*;
29
import java.io.*;
30
import java.nio.channels.*;
31
import com.sun.net.httpserver.*;
32
33
/**
34
*/
35
class Request {
36
37
final static int BUF_LEN = 2048;
38
final static byte CR = 13;
39
final static byte LF = 10;
40
41
private String startLine;
42
private SocketChannel chan;
43
private InputStream is;
44
private OutputStream os;
45
46
Request (InputStream rawInputStream, OutputStream rawout) throws IOException {
47
is = rawInputStream;
48
os = rawout;
49
do {
50
startLine = readLine();
51
if (startLine == null) {
52
return;
53
}
54
/* skip blank lines */
55
} while (startLine == null ? false : startLine.equals (""));
56
}
57
58
59
char[] buf = new char [BUF_LEN];
60
int pos;
61
StringBuffer lineBuf;
62
63
public InputStream inputStream () {
64
return is;
65
}
66
67
public OutputStream outputStream () {
68
return os;
69
}
70
71
/**
72
* read a line from the stream returning as a String.
73
* Not used for reading headers.
74
*/
75
76
public String readLine () throws IOException {
77
boolean gotCR = false, gotLF = false;
78
pos = 0; lineBuf = new StringBuffer();
79
while (!gotLF) {
80
int c = is.read();
81
if (c == -1) {
82
return null;
83
}
84
if (gotCR) {
85
if (c == LF) {
86
gotLF = true;
87
} else {
88
gotCR = false;
89
consume (CR);
90
consume (c);
91
}
92
} else {
93
if (c == CR) {
94
gotCR = true;
95
} else {
96
consume (c);
97
}
98
}
99
}
100
lineBuf.append (buf, 0, pos);
101
return new String (lineBuf);
102
}
103
104
private void consume (int c) {
105
if (pos == BUF_LEN) {
106
lineBuf.append (buf);
107
pos = 0;
108
}
109
buf[pos++] = (char)c;
110
}
111
112
/**
113
* returns the request line (first line of a request)
114
*/
115
public String requestLine () {
116
return startLine;
117
}
118
119
Headers hdrs = null;
120
@SuppressWarnings("fallthrough")
121
Headers headers () throws IOException {
122
if (hdrs != null) {
123
return hdrs;
124
}
125
hdrs = new Headers();
126
127
char s[] = new char[10];
128
int len = 0;
129
130
int firstc = is.read();
131
132
// check for empty headers
133
if (firstc == CR || firstc == LF) {
134
int c = is.read();
135
if (c == CR || c == LF) {
136
return hdrs;
137
}
138
s[0] = (char)firstc;
139
len = 1;
140
firstc = c;
141
}
142
143
while (firstc != LF && firstc != CR && firstc >= 0) {
144
int keyend = -1;
145
int c;
146
boolean inKey = firstc > ' ';
147
s[len++] = (char) firstc;
148
parseloop:{
149
while ((c = is.read()) >= 0) {
150
switch (c) {
151
/*fallthrough*/
152
case ':':
153
if (inKey && len > 0)
154
keyend = len;
155
inKey = false;
156
break;
157
case '\t':
158
c = ' ';
159
case ' ':
160
inKey = false;
161
break;
162
case CR:
163
case LF:
164
firstc = is.read();
165
if (c == CR && firstc == LF) {
166
firstc = is.read();
167
if (firstc == CR)
168
firstc = is.read();
169
}
170
if (firstc == LF || firstc == CR || firstc > ' ')
171
break parseloop;
172
/* continuation */
173
c = ' ';
174
break;
175
}
176
if (len >= s.length) {
177
char ns[] = new char[s.length * 2];
178
System.arraycopy(s, 0, ns, 0, len);
179
s = ns;
180
}
181
s[len++] = (char) c;
182
}
183
firstc = -1;
184
}
185
while (len > 0 && s[len - 1] <= ' ')
186
len--;
187
String k;
188
if (keyend <= 0) {
189
k = null;
190
keyend = 0;
191
} else {
192
k = String.copyValueOf(s, 0, keyend);
193
if (keyend < len && s[keyend] == ':')
194
keyend++;
195
while (keyend < len && s[keyend] <= ' ')
196
keyend++;
197
}
198
String v;
199
if (keyend >= len)
200
v = new String();
201
else
202
v = String.copyValueOf(s, keyend, len - keyend);
203
204
if (hdrs.size() >= ServerConfig.getMaxReqHeaders()) {
205
throw new IOException("Maximum number of request headers (" +
206
"sun.net.httpserver.maxReqHeaders) exceeded, " +
207
ServerConfig.getMaxReqHeaders() + ".");
208
}
209
if (k == null) { // Headers disallows null keys, use empty string
210
k = ""; // instead to represent invalid key
211
}
212
hdrs.add (k,v);
213
len = 0;
214
}
215
return hdrs;
216
}
217
218
/**
219
* Implements blocking reading semantics on top of a non-blocking channel
220
*/
221
222
static class ReadStream extends InputStream {
223
SocketChannel channel;
224
ByteBuffer chanbuf;
225
byte[] one;
226
private boolean closed = false, eof = false;
227
ByteBuffer markBuf; /* reads may be satisfied from this buffer */
228
boolean marked;
229
boolean reset;
230
int readlimit;
231
static long readTimeout;
232
ServerImpl server;
233
final static int BUFSIZE = 8 * 1024;
234
235
public ReadStream (ServerImpl server, SocketChannel chan) throws IOException {
236
this.channel = chan;
237
this.server = server;
238
chanbuf = ByteBuffer.allocate (BUFSIZE);
239
chanbuf.clear();
240
one = new byte[1];
241
closed = marked = reset = false;
242
}
243
244
public synchronized int read (byte[] b) throws IOException {
245
return read (b, 0, b.length);
246
}
247
248
public synchronized int read () throws IOException {
249
int result = read (one, 0, 1);
250
if (result == 1) {
251
return one[0] & 0xFF;
252
} else {
253
return -1;
254
}
255
}
256
257
public synchronized int read (byte[] b, int off, int srclen) throws IOException {
258
259
int canreturn, willreturn;
260
261
if (closed)
262
throw new IOException ("Stream closed");
263
264
if (eof) {
265
return -1;
266
}
267
268
assert channel.isBlocking();
269
270
if (off < 0 || srclen < 0|| srclen > (b.length-off)) {
271
throw new IndexOutOfBoundsException ();
272
}
273
274
if (reset) { /* satisfy from markBuf */
275
canreturn = markBuf.remaining ();
276
willreturn = canreturn>srclen ? srclen : canreturn;
277
markBuf.get(b, off, willreturn);
278
if (canreturn == willreturn) {
279
reset = false;
280
}
281
} else { /* satisfy from channel */
282
chanbuf.clear ();
283
if (srclen < BUFSIZE) {
284
chanbuf.limit (srclen);
285
}
286
do {
287
willreturn = channel.read (chanbuf);
288
} while (willreturn == 0);
289
if (willreturn == -1) {
290
eof = true;
291
return -1;
292
}
293
chanbuf.flip ();
294
chanbuf.get(b, off, willreturn);
295
296
if (marked) { /* copy into markBuf */
297
try {
298
markBuf.put (b, off, willreturn);
299
} catch (BufferOverflowException e) {
300
marked = false;
301
}
302
}
303
}
304
return willreturn;
305
}
306
307
public boolean markSupported () {
308
return true;
309
}
310
311
/* Does not query the OS socket */
312
public synchronized int available () throws IOException {
313
if (closed)
314
throw new IOException ("Stream is closed");
315
316
if (eof)
317
return -1;
318
319
if (reset)
320
return markBuf.remaining();
321
322
return chanbuf.remaining();
323
}
324
325
public void close () throws IOException {
326
if (closed) {
327
return;
328
}
329
channel.close ();
330
closed = true;
331
}
332
333
public synchronized void mark (int readlimit) {
334
if (closed)
335
return;
336
this.readlimit = readlimit;
337
markBuf = ByteBuffer.allocate (readlimit);
338
marked = true;
339
reset = false;
340
}
341
342
public synchronized void reset () throws IOException {
343
if (closed )
344
return;
345
if (!marked)
346
throw new IOException ("Stream not marked");
347
marked = false;
348
reset = true;
349
markBuf.flip ();
350
}
351
}
352
353
static class WriteStream extends java.io.OutputStream {
354
SocketChannel channel;
355
ByteBuffer buf;
356
SelectionKey key;
357
boolean closed;
358
byte[] one;
359
ServerImpl server;
360
361
public WriteStream (ServerImpl server, SocketChannel channel) throws IOException {
362
this.channel = channel;
363
this.server = server;
364
assert channel.isBlocking();
365
closed = false;
366
one = new byte [1];
367
buf = ByteBuffer.allocate (4096);
368
}
369
370
public synchronized void write (int b) throws IOException {
371
one[0] = (byte)b;
372
write (one, 0, 1);
373
}
374
375
public synchronized void write (byte[] b) throws IOException {
376
write (b, 0, b.length);
377
}
378
379
public synchronized void write (byte[] b, int off, int len) throws IOException {
380
int l = len;
381
if (closed)
382
throw new IOException ("stream is closed");
383
384
int cap = buf.capacity();
385
if (cap < len) {
386
int diff = len - cap;
387
buf = ByteBuffer.allocate (2*(cap+diff));
388
}
389
buf.clear();
390
buf.put (b, off, len);
391
buf.flip ();
392
int n;
393
while ((n = channel.write (buf)) < l) {
394
l -= n;
395
if (l == 0)
396
return;
397
}
398
}
399
400
public void close () throws IOException {
401
if (closed)
402
return;
403
//server.logStackTrace ("Request.OS.close: isOpen="+channel.isOpen());
404
channel.close ();
405
closed = true;
406
}
407
}
408
}
409
410