24 */ |
24 */ |
25 |
25 |
26 package jdk.internal.net.http; |
26 package jdk.internal.net.http; |
27 |
27 |
28 import java.io.IOException; |
28 import java.io.IOException; |
29 import java.lang.System.Logger.Level; |
|
30 import java.net.InetSocketAddress; |
29 import java.net.InetSocketAddress; |
|
30 import java.net.http.HttpTimeoutException; |
31 import java.nio.ByteBuffer; |
31 import java.nio.ByteBuffer; |
32 import java.nio.channels.SocketChannel; |
32 import java.nio.channels.SocketChannel; |
|
33 import java.time.Duration; |
33 import java.util.concurrent.CompletableFuture; |
34 import java.util.concurrent.CompletableFuture; |
|
35 import java.util.concurrent.CompletionException; |
34 import java.util.function.Function; |
36 import java.util.function.Function; |
35 import java.net.http.HttpHeaders; |
37 import java.net.http.HttpHeaders; |
36 import jdk.internal.net.http.common.FlowTube; |
38 import jdk.internal.net.http.common.FlowTube; |
37 import jdk.internal.net.http.common.MinimalFuture; |
39 import jdk.internal.net.http.common.MinimalFuture; |
38 import static java.net.http.HttpResponse.BodyHandlers.discarding; |
40 import static java.net.http.HttpResponse.BodyHandlers.discarding; |
58 this.proxyHeaders = proxyHeaders; |
60 this.proxyHeaders = proxyHeaders; |
59 delegate = new PlainHttpConnection(proxy, client); |
61 delegate = new PlainHttpConnection(proxy, client); |
60 } |
62 } |
61 |
63 |
62 @Override |
64 @Override |
63 public CompletableFuture<Void> connectAsync() { |
65 public CompletableFuture<Void> connectAsync(Exchange<?> exchange) { |
64 if (debug.on()) debug.log("Connecting plain connection"); |
66 if (debug.on()) debug.log("Connecting plain connection"); |
65 return delegate.connectAsync() |
67 return delegate.connectAsync(exchange) |
|
68 .thenCompose(unused -> delegate.finishConnect()) |
66 .thenCompose((Void v) -> { |
69 .thenCompose((Void v) -> { |
67 if (debug.on()) debug.log("sending HTTP/1.1 CONNECT"); |
70 if (debug.on()) debug.log("sending HTTP/1.1 CONNECT"); |
68 HttpClientImpl client = client(); |
71 HttpClientImpl client = client(); |
69 assert client != null; |
72 assert client != null; |
70 HttpRequestImpl req = new HttpRequestImpl("CONNECT", address, proxyHeaders); |
73 HttpRequestImpl req = new HttpRequestImpl("CONNECT", address, proxyHeaders); |
71 MultiExchange<Void> mulEx = new MultiExchange<>(null, req, |
74 MultiExchange<Void> mulEx = new MultiExchange<>(null, req, |
72 client, discarding(), null, null); |
75 client, discarding(), null, null); |
73 Exchange<Void> connectExchange = new Exchange<>(req, mulEx); |
76 Exchange<Void> connectExchange = mulEx.getExchange(); |
74 |
77 |
75 return connectExchange |
78 return connectExchange |
76 .responseAsyncImpl(delegate) |
79 .responseAsyncImpl(delegate) |
77 .thenCompose((Response resp) -> { |
80 .thenCompose((Response resp) -> { |
78 CompletableFuture<Void> cf = new MinimalFuture<>(); |
81 CompletableFuture<Void> cf = new MinimalFuture<>(); |
94 } else { |
97 } else { |
95 // get the initial/remaining bytes |
98 // get the initial/remaining bytes |
96 ByteBuffer b = ((Http1Exchange<?>)connectExchange.exchImpl).drainLeftOverBytes(); |
99 ByteBuffer b = ((Http1Exchange<?>)connectExchange.exchImpl).drainLeftOverBytes(); |
97 int remaining = b.remaining(); |
100 int remaining = b.remaining(); |
98 assert remaining == 0: "Unexpected remaining: " + remaining; |
101 assert remaining == 0: "Unexpected remaining: " + remaining; |
99 connected = true; |
|
100 cf.complete(null); |
102 cf.complete(null); |
101 } |
103 } |
102 return cf; |
104 return cf; |
103 }); |
105 }) |
|
106 .handle((result, ex) -> { |
|
107 if (ex == null) { |
|
108 return MinimalFuture.completedFuture(result); |
|
109 } else { |
|
110 if (debug.on()) |
|
111 debug.log("tunnel failed with \"%s\"", ex.toString()); |
|
112 Throwable t = ex; |
|
113 if (t instanceof CompletionException) |
|
114 t = t.getCause(); |
|
115 if (t instanceof HttpTimeoutException) { |
|
116 String msg = "proxy tunneling CONNECT request timed out"; |
|
117 t = new HttpTimeoutException(msg); |
|
118 t.initCause(ex); |
|
119 } |
|
120 return MinimalFuture.<Void>failedFuture(t); |
|
121 } |
|
122 }) |
|
123 .thenCompose(Function.identity()); |
104 }); |
124 }); |
|
125 } |
|
126 |
|
127 public CompletableFuture<Void> finishConnect() { |
|
128 connected = true; |
|
129 return MinimalFuture.completedFuture(null); |
105 } |
130 } |
106 |
131 |
107 @Override |
132 @Override |
108 boolean isTunnel() { return true; } |
133 boolean isTunnel() { return true; } |
109 |
134 |