Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java
41171 views
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
23
* questions.
24
*/
25
26
package jdk.internal.net.http;
27
28
import java.io.IOException;
29
import java.net.http.HttpClient;
30
import java.net.http.HttpResponse;
31
import java.util.concurrent.CompletableFuture;
32
import java.util.concurrent.Executor;
33
34
import jdk.internal.net.http.common.Logger;
35
import jdk.internal.net.http.common.MinimalFuture;
36
import jdk.internal.net.http.common.Utils;
37
38
import static java.net.http.HttpClient.Version.HTTP_1_1;
39
40
/**
41
* Splits request so that headers and body can be sent separately with optional
42
* (multiple) responses in between (e.g. 100 Continue). Also request and
43
* response always sent/received in different calls.
44
*
45
* Synchronous and asynchronous versions of each method are provided.
46
*
47
* Separate implementations of this class exist for HTTP/1.1 and HTTP/2
48
* Http1Exchange (HTTP/1.1)
49
* Stream (HTTP/2)
50
*
51
* These implementation classes are where work is allocated to threads.
52
*/
53
abstract class ExchangeImpl<T> {
54
55
private static final Logger debug =
56
Utils.getDebugLogger("ExchangeImpl"::toString, Utils.DEBUG);
57
58
final Exchange<T> exchange;
59
60
ExchangeImpl(Exchange<T> e) {
61
// e == null means a http/2 pushed stream
62
this.exchange = e;
63
}
64
65
final Exchange<T> getExchange() {
66
return exchange;
67
}
68
69
HttpClient client() {
70
return exchange.client();
71
}
72
73
/**
74
* Returns the {@link HttpConnection} instance to which this exchange is
75
* assigned.
76
*/
77
abstract HttpConnection connection();
78
79
/**
80
* Initiates a new exchange and assigns it to a connection if one exists
81
* already. connection usually null.
82
*/
83
static <U> CompletableFuture<? extends ExchangeImpl<U>>
84
get(Exchange<U> exchange, HttpConnection connection)
85
{
86
if (exchange.version() == HTTP_1_1) {
87
if (debug.on())
88
debug.log("get: HTTP/1.1: new Http1Exchange");
89
return createHttp1Exchange(exchange, connection);
90
} else {
91
Http2ClientImpl c2 = exchange.client().client2(); // #### improve
92
HttpRequestImpl request = exchange.request();
93
CompletableFuture<Http2Connection> c2f = c2.getConnectionFor(request, exchange);
94
if (debug.on())
95
debug.log("get: Trying to get HTTP/2 connection");
96
// local variable required here; see JDK-8223553
97
CompletableFuture<CompletableFuture<? extends ExchangeImpl<U>>> fxi =
98
c2f.handle((h2c, t) -> createExchangeImpl(h2c, t, exchange, connection));
99
return fxi.thenCompose(x->x);
100
}
101
}
102
103
private static <U> CompletableFuture<? extends ExchangeImpl<U>>
104
createExchangeImpl(Http2Connection c,
105
Throwable t,
106
Exchange<U> exchange,
107
HttpConnection connection)
108
{
109
if (debug.on())
110
debug.log("handling HTTP/2 connection creation result");
111
boolean secure = exchange.request().secure();
112
if (t != null) {
113
if (debug.on())
114
debug.log("handling HTTP/2 connection creation failed: %s",
115
(Object)t);
116
t = Utils.getCompletionCause(t);
117
if (t instanceof Http2Connection.ALPNException) {
118
Http2Connection.ALPNException ee = (Http2Connection.ALPNException)t;
119
AbstractAsyncSSLConnection as = ee.getConnection();
120
if (debug.on())
121
debug.log("downgrading to HTTP/1.1 with: %s", as);
122
CompletableFuture<? extends ExchangeImpl<U>> ex =
123
createHttp1Exchange(exchange, as);
124
return ex;
125
} else {
126
if (debug.on())
127
debug.log("HTTP/2 connection creation failed "
128
+ "with unexpected exception: %s", (Object)t);
129
return MinimalFuture.failedFuture(t);
130
}
131
}
132
if (secure && c== null) {
133
if (debug.on())
134
debug.log("downgrading to HTTP/1.1 ");
135
CompletableFuture<? extends ExchangeImpl<U>> ex =
136
createHttp1Exchange(exchange, null);
137
return ex;
138
}
139
if (c == null) {
140
// no existing connection. Send request with HTTP 1 and then
141
// upgrade if successful
142
if (debug.on())
143
debug.log("new Http1Exchange, try to upgrade");
144
return createHttp1Exchange(exchange, connection)
145
.thenApply((e) -> {
146
exchange.h2Upgrade();
147
return e;
148
});
149
} else {
150
if (debug.on()) debug.log("creating HTTP/2 streams");
151
Stream<U> s = c.createStream(exchange);
152
CompletableFuture<? extends ExchangeImpl<U>> ex = MinimalFuture.completedFuture(s);
153
return ex;
154
}
155
}
156
157
private static <T> CompletableFuture<Http1Exchange<T>>
158
createHttp1Exchange(Exchange<T> ex, HttpConnection as)
159
{
160
try {
161
return MinimalFuture.completedFuture(new Http1Exchange<>(ex, as));
162
} catch (Throwable e) {
163
return MinimalFuture.failedFuture(e);
164
}
165
}
166
167
// Called for 204 response - when no body is permitted
168
void nullBody(HttpResponse<T> resp, Throwable t) {
169
// Needed for HTTP/1.1 to close the connection or return it to the pool
170
// Needed for HTTP/2 to subscribe a dummy subscriber and close the stream
171
}
172
173
/* The following methods have separate HTTP/1.1 and HTTP/2 implementations */
174
175
abstract CompletableFuture<ExchangeImpl<T>> sendHeadersAsync();
176
177
/** Sends a request body, after request headers have been sent. */
178
abstract CompletableFuture<ExchangeImpl<T>> sendBodyAsync();
179
180
abstract CompletableFuture<T> readBodyAsync(HttpResponse.BodyHandler<T> handler,
181
boolean returnConnectionToPool,
182
Executor executor);
183
184
/**
185
* Ignore/consume the body.
186
*/
187
abstract CompletableFuture<Void> ignoreBody();
188
189
190
/** Gets the response headers. Completes before body is read. */
191
abstract CompletableFuture<Response> getResponseAsync(Executor executor);
192
193
194
/** Cancels a request. Not currently exposed through API. */
195
abstract void cancel();
196
197
/**
198
* Cancels a request with a cause. Not currently exposed through API.
199
*/
200
abstract void cancel(IOException cause);
201
202
/**
203
* Called when the exchange is released, so that cleanup actions may be
204
* performed - such as deregistering callbacks.
205
* Typically released is called during upgrade, when an HTTP/2 stream
206
* takes over from an Http1Exchange, or when a new exchange is created
207
* during a multi exchange before the final response body was received.
208
*/
209
abstract void released();
210
211
/**
212
* Called when the exchange is completed, so that cleanup actions may be
213
* performed - such as deregistering callbacks.
214
* Typically, completed is called at the end of the exchange, when the
215
* final response body has been received (or an error has caused the
216
* completion of the exchange).
217
*/
218
abstract void completed();
219
220
/**
221
* Returns true if this exchange was canceled.
222
* @return true if this exchange was canceled.
223
*/
224
abstract boolean isCanceled();
225
226
/**
227
* Returns the cause for which this exchange was canceled, if available.
228
* @return the cause for which this exchange was canceled, if available.
229
*/
230
abstract Throwable getCancelCause();
231
232
// Mark the exchange as upgraded
233
// Needed to handle cancellation during the upgrade from
234
// Http1Exchange to Stream
235
void upgraded() { }
236
}
237
238