1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.http.impl.nio;
29
30 import java.net.InetAddress;
31 import java.net.InetSocketAddress;
32 import java.net.SocketAddress;
33 import java.util.concurrent.Future;
34
35 import org.apache.hc.client5.http.DnsResolver;
36 import org.apache.hc.client5.http.SchemePortResolver;
37 import org.apache.hc.client5.http.config.TlsConfig;
38 import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
39 import org.apache.hc.client5.http.nio.AsyncClientConnectionOperator;
40 import org.apache.hc.client5.http.nio.ManagedAsyncClientConnection;
41 import org.apache.hc.client5.http.routing.RoutingSupport;
42 import org.apache.hc.core5.concurrent.CallbackContribution;
43 import org.apache.hc.core5.concurrent.ComplexFuture;
44 import org.apache.hc.core5.concurrent.FutureCallback;
45 import org.apache.hc.core5.concurrent.FutureContribution;
46 import org.apache.hc.core5.http.HttpHost;
47 import org.apache.hc.core5.http.URIScheme;
48 import org.apache.hc.core5.http.config.Lookup;
49 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
50 import org.apache.hc.core5.http.protocol.HttpContext;
51 import org.apache.hc.core5.reactor.ConnectionInitiator;
52 import org.apache.hc.core5.reactor.IOSession;
53 import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
54 import org.apache.hc.core5.util.Args;
55 import org.apache.hc.core5.util.Timeout;
56
57 final class DefaultAsyncClientConnectionOperator implements AsyncClientConnectionOperator {
58
59 private final SchemePortResolver schemePortResolver;
60 private final MultihomeIOSessionRequester sessionRequester;
61 private final Lookup<TlsStrategy> tlsStrategyLookup;
62
63 DefaultAsyncClientConnectionOperator(
64 final Lookup<TlsStrategy> tlsStrategyLookup,
65 final SchemePortResolver schemePortResolver,
66 final DnsResolver dnsResolver) {
67 this.tlsStrategyLookup = Args.notNull(tlsStrategyLookup, "TLS strategy lookup");
68 this.schemePortResolver = schemePortResolver != null ? schemePortResolver : DefaultSchemePortResolver.INSTANCE;
69 this.sessionRequester = new MultihomeIOSessionRequester(dnsResolver);
70 }
71
72 @Override
73 public Future<ManagedAsyncClientConnection> connect(
74 final ConnectionInitiator connectionInitiator,
75 final HttpHost host,
76 final SocketAddress localAddress,
77 final Timeout connectTimeout,
78 final Object attachment,
79 final FutureCallback<ManagedAsyncClientConnection> callback) {
80 return connect(connectionInitiator, host, localAddress, connectTimeout,
81 attachment, null, callback);
82 }
83
84 @Override
85 public Future<ManagedAsyncClientConnection> connect(
86 final ConnectionInitiator connectionInitiator,
87 final HttpHost host,
88 final SocketAddress localAddress,
89 final Timeout connectTimeout,
90 final Object attachment,
91 final HttpContext context,
92 final FutureCallback<ManagedAsyncClientConnection> callback) {
93 Args.notNull(connectionInitiator, "Connection initiator");
94 Args.notNull(host, "Host");
95 final ComplexFuture<ManagedAsyncClientConnection> future = new ComplexFuture<>(callback);
96 final HttpHost remoteEndpoint = RoutingSupport.normalize(host, schemePortResolver);
97 final InetAddress remoteAddress = host.getAddress();
98 final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(host.getSchemeName()) : null;
99 final TlsConfig tlsConfig = attachment instanceof TlsConfig ? (TlsConfig) attachment : TlsConfig.DEFAULT;
100 final Future<IOSession> sessionFuture = sessionRequester.connect(
101 connectionInitiator,
102 remoteEndpoint,
103 remoteAddress != null ? new InetSocketAddress(remoteAddress, remoteEndpoint.getPort()) : null,
104 localAddress,
105 connectTimeout,
106 tlsConfig.getHttpVersionPolicy(),
107 new FutureCallback<IOSession>() {
108
109 @Override
110 public void completed(final IOSession session) {
111 final DefaultManagedAsyncClientConnection connection = new DefaultManagedAsyncClientConnection(session);
112 if (tlsStrategy != null && URIScheme.HTTPS.same(host.getSchemeName())) {
113 try {
114 final Timeout socketTimeout = connection.getSocketTimeout();
115 final Timeout handshakeTimeout = tlsConfig.getHandshakeTimeout();
116 tlsStrategy.upgrade(
117 connection,
118 host,
119 attachment,
120 handshakeTimeout != null ? handshakeTimeout : connectTimeout,
121 new FutureContribution<TransportSecurityLayer>(future) {
122
123 @Override
124 public void completed(final TransportSecurityLayer transportSecurityLayer) {
125 connection.setSocketTimeout(socketTimeout);
126 future.completed(connection);
127 }
128
129 });
130 } catch (final Exception ex) {
131 future.failed(ex);
132 }
133 } else {
134 future.completed(connection);
135 }
136 }
137
138 @Override
139 public void failed(final Exception ex) {
140 future.failed(ex);
141 }
142
143 @Override
144 public void cancelled() {
145 future.cancel();
146 }
147
148 });
149 future.setDependency(sessionFuture);
150 return future;
151 }
152
153 @Override
154 public void upgrade(
155 final ManagedAsyncClientConnection connection,
156 final HttpHost host,
157 final Object attachment) {
158 upgrade(connection, host, attachment, null, null);
159 }
160
161 @Override
162 public void upgrade(
163 final ManagedAsyncClientConnection connection,
164 final HttpHost host,
165 final Object attachment,
166 final HttpContext context) {
167 upgrade(connection, host, attachment, context, null);
168 }
169
170 @Override
171 public void upgrade(
172 final ManagedAsyncClientConnection connection,
173 final HttpHost host,
174 final Object attachment,
175 final HttpContext context,
176 final FutureCallback<ManagedAsyncClientConnection> callback) {
177 final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(host.getSchemeName()) : null;
178 if (tlsStrategy != null) {
179 tlsStrategy.upgrade(
180 connection,
181 host,
182 attachment,
183 null,
184 new CallbackContribution<TransportSecurityLayer>(callback) {
185
186 @Override
187 public void completed(final TransportSecurityLayer transportSecurityLayer) {
188 if (callback != null) {
189 callback.completed(connection);
190 }
191 }
192
193 });
194 }
195
196 }
197
198 }