< prev index next >
1 /*
2 * Copyright (c) 2015, 2016, 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 */
24 package java.net.http;
25
26 import sun.net.NetProperties;
27
28 import javax.net.ssl.SSLParameters;
29 import java.io.ByteArrayOutputStream;
30 import java.io.Closeable;
31 import java.io.IOException;
32 import java.io.PrintStream;
33 import java.io.UnsupportedEncodingException;
34 import java.net.InetSocketAddress;
35 import java.net.NetPermission;
36 import java.net.URI;
37 import java.net.URLPermission;
38 import java.nio.Buffer;
39 import java.nio.ByteBuffer;
40 import java.nio.charset.StandardCharsets;
41 import java.security.AccessController;
42 import java.security.PrivilegedAction;
43 import java.util.Arrays;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Set;
47 import java.util.concurrent.CompletableFuture;
48 import java.util.function.LongBinaryOperator;
49 import java.util.function.Predicate;
50
51 /**
52 * Miscellaneous utilities
53 */
54 final class Utils {
55
56 /**
57 * Allocated buffer size. Must never be higher than 16K. But can be lower
58 * if smaller allocation units preferred. HTTP/2 mandates that all
59 * implementations support frame payloads of at least 16K.
60 */
61 public static final int BUFSIZE = 16 * 1024;
62
63 private static final Set<String> DISALLOWED_HEADERS_SET = Set.of(
64 "authorization", "connection", "cookie", "content-length",
65 "date", "expect", "from", "host", "origin", "proxy-authorization",
66 "referer", "user-agent", "upgrade", "via", "warning");
67
68 static final Predicate<String>
69 ALLOWED_HEADERS = header -> !Utils.DISALLOWED_HEADERS_SET.contains(header);
70
71 static final Predicate<String>
72 ALL_HEADERS = header -> true;
73
74 static InetSocketAddress getAddress(HttpRequestImpl req) {
75 URI uri = req.uri();
76 if (uri == null) {
77 return req.authority();
78 }
79 int port = uri.getPort();
80 if (port == -1) {
81 if (uri.getScheme().equalsIgnoreCase("https")) {
82 port = 443;
83 } else {
84 port = 80;
85 }
86 }
87 String host = uri.getHost();
88 if (req.proxy() == null) {
89 return new InetSocketAddress(host, port);
90 } else {
91 return InetSocketAddress.createUnresolved(host, port);
92 }
93 }
94
95 /**
96 * Puts position to limit and limit to capacity so we can resume reading
97 * into this buffer, but if required > 0 then limit may be reduced so that
98 * no more than required bytes are read next time.
99 */
100 static void resumeChannelRead(ByteBuffer buf, int required) {
101 int limit = buf.limit();
102 buf.position(limit);
103 int capacity = buf.capacity() - limit;
104 if (required > 0 && required < capacity) {
105 buf.limit(limit + required);
106 } else {
107 buf.limit(buf.capacity());
108 }
109 }
110
111 private Utils() { }
112
113 /**
114 * Validates a RFC7230 token
115 */
116 static void validateToken(String token, String errormsg) {
117 int length = token.length();
118 for (int i = 0; i < length; i++) {
119 int c = token.codePointAt(i);
120 if (c >= 0x30 && c <= 0x39 // 0 - 9
121 || (c >= 0x61 && c <= 0x7a) // a - z
122 || (c >= 0x41 && c <= 0x5a) // A - Z
123 || (c >= 0x21 && c <= 0x2e && c != 0x22 && c != 0x27 && c != 0x2c)
124 || (c >= 0x5e && c <= 0x60)
125 || (c == 0x7c) || (c == 0x7e)) {
126 } else {
127 throw new IllegalArgumentException(errormsg);
128 }
129 }
130 }
131
132 /**
133 * Returns the security permission required for the given details.
134 * If method is CONNECT, then uri must be of form "scheme://host:port"
135 */
136 static URLPermission getPermission(URI uri,
137 String method,
138 Map<String, List<String>> headers) {
139 StringBuilder sb = new StringBuilder();
140
141 String urlstring, actionstring;
142
143 if (method.equals("CONNECT")) {
144 urlstring = uri.toString();
145 actionstring = "CONNECT";
146 } else {
147 sb.append(uri.getScheme())
148 .append("://")
149 .append(uri.getHost())
150 .append(uri.getPath());
151 urlstring = sb.toString();
152
153 sb = new StringBuilder();
154 sb.append(method);
155 if (headers != null && !headers.isEmpty()) {
156 sb.append(':');
157 Set<String> keys = headers.keySet();
158 boolean first = true;
159 for (String key : keys) {
160 if (!first) {
161 sb.append(',');
162 }
163 sb.append(key);
164 first = false;
165 }
166 }
167 actionstring = sb.toString();
168 }
169 return new URLPermission(urlstring, actionstring);
170 }
171
172 static void checkNetPermission(String target) {
173 SecurityManager sm = System.getSecurityManager();
174 if (sm == null)
175 return;
176 NetPermission np = new NetPermission(target);
177 sm.checkPermission(np);
178 }
179
180 static int getIntegerNetProperty(String name, int defaultValue) {
181 return AccessController.doPrivileged((PrivilegedAction<Integer>) () ->
182 NetProperties.getInteger(name, defaultValue));
183 }
184
185 static String getNetProperty(String name) {
186 return AccessController.doPrivileged((PrivilegedAction<String>) () ->
187 NetProperties.get(name));
188 }
189
190 static SSLParameters copySSLParameters(SSLParameters p) {
191 SSLParameters p1 = new SSLParameters();
192 p1.setAlgorithmConstraints(p.getAlgorithmConstraints());
193 p1.setCipherSuites(p.getCipherSuites());
194 p1.setEnableRetransmissions(p.getEnableRetransmissions());
195 p1.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm());
196 p1.setMaximumPacketSize(p.getMaximumPacketSize());
197 p1.setNeedClientAuth(p.getNeedClientAuth());
198 String[] protocols = p.getProtocols();
199 if (protocols != null)
200 p1.setProtocols(protocols.clone());
201 p1.setSNIMatchers(p.getSNIMatchers());
202 p1.setServerNames(p.getServerNames());
203 p1.setUseCipherSuitesOrder(p.getUseCipherSuitesOrder());
204 p1.setWantClientAuth(p.getWantClientAuth());
205 return p1;
206 }
207
208 /**
209 * Set limit to position, and position to mark.
210 */
211 static void flipToMark(ByteBuffer buffer, int mark) {
212 buffer.limit(buffer.position());
213 buffer.position(mark);
214 }
215
216 static String stackTrace(Throwable t) {
217 ByteArrayOutputStream bos = new ByteArrayOutputStream();
218 String s = null;
219 try {
220 PrintStream p = new PrintStream(bos, true, "US-ASCII");
221 t.printStackTrace(p);
222 s = bos.toString("US-ASCII");
223 } catch (UnsupportedEncodingException ex) {
224 // can't happen
225 }
226 return s;
227 }
228
229 /**
230 * Copies as much of src to dst as possible.
231 */
232 static void copy(ByteBuffer src, ByteBuffer dst) {
233 int srcLen = src.remaining();
234 int dstLen = dst.remaining();
235 if (srcLen > dstLen) {
236 int diff = srcLen - dstLen;
237 int limit = src.limit();
238 src.limit(limit - diff);
239 dst.put(src);
240 src.limit(limit);
241 } else {
242 dst.put(src);
243 }
244 }
245
246 static ByteBuffer copy(ByteBuffer src) {
247 ByteBuffer dst = ByteBuffer.allocate(src.remaining());
248 dst.put(src);
249 dst.flip();
250 return dst;
251 }
252
253 //
254 // Helps to trim long names (packages, nested/inner types) in logs/toString
255 //
256 static String toStringSimple(Object o) {
257 return o.getClass().getSimpleName() + "@" +
258 Integer.toHexString(System.identityHashCode(o));
259 }
260
261 //
262 // 1. It adds a number of remaining bytes;
263 // 2. Standard Buffer-type toString for CharBuffer (since it adheres to the
264 // contract of java.lang.CharSequence.toString() which is both not too
265 // useful and not too private)
266 //
267 static String toString(Buffer b) {
268 return toStringSimple(b)
269 + "[pos=" + b.position()
270 + " lim=" + b.limit()
271 + " cap=" + b.capacity()
272 + " rem=" + b.remaining() + "]";
273 }
274
275 static String toString(CharSequence s) {
276 return s == null
277 ? "null"
278 : toStringSimple(s) + "[len=" + s.length() + "]";
279 }
280
281 static String dump(Object... objects) {
282 return Arrays.toString(objects);
283 }
284
285 static final System.Logger logger = System.getLogger("java.net.http.WebSocket");
286
287 static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0);
288
289 static String webSocketSpecViolation(String section, String detail) {
290 return "RFC 6455 " + section + " " + detail;
291 }
292
293 static void logResponse(HttpResponseImpl r) {
294 if (!Log.requests()) {
295 return;
296 }
297 StringBuilder sb = new StringBuilder();
298 String method = r.request().method();
299 URI uri = r.uri();
300 String uristring = uri == null ? "" : uri.toString();
301 sb.append('(').append(method).append(" ").append(uristring).append(") ").append(Integer.toString(r.statusCode()));
302 Log.logResponse(sb.toString());
303 }
304
305 static int remaining(ByteBuffer[] bufs) {
306 int remain = 0;
307 for (ByteBuffer buf : bufs)
308 remain += buf.remaining();
309 return remain;
310 }
311
312 // assumes buffer was written into starting at position zero
313 static void unflip(ByteBuffer buf) {
314 buf.position(buf.limit());
315 buf.limit(buf.capacity());
316 }
317
318 static void close(Closeable... chans) {
319 for (Closeable chan : chans) {
320 System.err.println("Closing " + chan);
321 try {
322 chan.close();
323 } catch (IOException e) {
324 }
325 }
326 }
327
328 static ByteBuffer[] reduce(ByteBuffer[] bufs, int start, int number) {
329 if (start == 0 && number == bufs.length)
330 return bufs;
331 ByteBuffer[] nbufs = new ByteBuffer[number];
332 int j = 0;
333 for (int i=start; i<start+number; i++)
334 nbufs[j++] = bufs[i];
335 return nbufs;
336 }
337
338 static String asString(ByteBuffer buf) {
339 byte[] b = new byte[buf.remaining()];
340 buf.get(b);
341 return new String(b, StandardCharsets.US_ASCII);
342 }
343
344 // Put all these static 'empty' singletons here
345 @SuppressWarnings("rawtypes")
346 static CompletableFuture[] EMPTY_CFARRAY = new CompletableFuture[0];
347
348 static ByteBuffer EMPTY_BYTEBUFFER = ByteBuffer.allocate(0);
349 static ByteBuffer[] EMPTY_BB_ARRAY = new ByteBuffer[0];
350 }
< prev index next >