1 /*
2 * Copyright (c) 2015, 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. 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
198 */
199 static final class Result {
200
201 final String subprotocol;
202 final TransportFactory transport;
203
204 private Result(String subprotocol, TransportFactory transport) {
205 this.subprotocol = subprotocol;
206 this.transport = transport;
207 }
208 }
209
210 private CompletableFuture<Result> resultFrom(HttpResponse<?> response) {
211 // Do we need a special treatment for SSLHandshakeException?
212 // Namely, invoking
213 //
214 // Listener.onClose(StatusCodes.TLS_HANDSHAKE_FAILURE, "")
215 //
216 // See https://tools.ietf.org/html/rfc6455#section-7.4.1
217 Result result = null;
218 Exception exception = null;
219 try {
220 result = handleResponse(response);
221 } catch (IOException e) {
222 exception = e;
223 } catch (Exception e) {
224 exception = new WebSocketHandshakeException(response).initCause(e);
225 }
226 if (exception == null) {
227 return MinimalFuture.completedFuture(result);
228 }
229 try {
230 ((RawChannel.Provider) response).rawChannel().close();
231 } catch (IOException e) {
232 exception.addSuppressed(e);
233 }
234 return MinimalFuture.failedFuture(exception);
235 }
236
237 private Result handleResponse(HttpResponse<?> response) throws IOException {
238 // By this point all redirects, authentications, etc. (if any) MUST have
239 // been done by the HttpClient used by the WebSocket; so only 101 is
240 // expected
241 int c = response.statusCode();
242 if (c != 101) {
243 throw checkFailed("Unexpected HTTP response status code " + c);
244 }
245 HttpHeaders headers = response.headers();
246 String upgrade = requireSingle(headers, HEADER_UPGRADE);
247 if (!upgrade.equalsIgnoreCase("websocket")) {
248 throw checkFailed("Bad response field: " + HEADER_UPGRADE);
249 }
250 String connection = requireSingle(headers, HEADER_CONNECTION);
|
1 /*
2 * Copyright (c) 2015, 2020, 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
198 */
199 static final class Result {
200
201 final String subprotocol;
202 final TransportFactory transport;
203
204 private Result(String subprotocol, TransportFactory transport) {
205 this.subprotocol = subprotocol;
206 this.transport = transport;
207 }
208 }
209
210 private CompletableFuture<Result> resultFrom(HttpResponse<?> response) {
211 // Do we need a special treatment for SSLHandshakeException?
212 // Namely, invoking
213 //
214 // Listener.onClose(StatusCodes.TLS_HANDSHAKE_FAILURE, "")
215 //
216 // See https://tools.ietf.org/html/rfc6455#section-7.4.1
217 Result result = null;
218 Throwable exception = null;
219 try {
220 result = handleResponse(response);
221 } catch (IOException e) {
222 exception = e;
223 } catch (Exception e) {
224 exception = new WebSocketHandshakeException(response).initCause(e);
225 } catch (Error e) {
226 // We should attempt to close the connection and relay
227 // the error through the completable future even in this
228 // case.
229 exception = e;
230 }
231 if (exception == null) {
232 return MinimalFuture.completedFuture(result);
233 }
234 try {
235 // calling this method will close the rawChannel, if created,
236 // or the connection, if not.
237 ((RawChannel.Provider) response).closeRawChannel();
238 } catch (IOException e) {
239 exception.addSuppressed(e);
240 }
241 return MinimalFuture.failedFuture(exception);
242 }
243
244 private Result handleResponse(HttpResponse<?> response) throws IOException {
245 // By this point all redirects, authentications, etc. (if any) MUST have
246 // been done by the HttpClient used by the WebSocket; so only 101 is
247 // expected
248 int c = response.statusCode();
249 if (c != 101) {
250 throw checkFailed("Unexpected HTTP response status code " + c);
251 }
252 HttpHeaders headers = response.headers();
253 String upgrade = requireSingle(headers, HEADER_UPGRADE);
254 if (!upgrade.equalsIgnoreCase("websocket")) {
255 throw checkFailed("Bad response field: " + HEADER_UPGRADE);
256 }
257 String connection = requireSingle(headers, HEADER_CONNECTION);
|