View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
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.impl.DefaultSchemePortResolver;
38  import org.apache.hc.client5.http.nio.AsyncClientConnectionOperator;
39  import org.apache.hc.client5.http.nio.ManagedAsyncClientConnection;
40  import org.apache.hc.client5.http.routing.RoutingSupport;
41  import org.apache.hc.core5.concurrent.ComplexFuture;
42  import org.apache.hc.core5.concurrent.FutureCallback;
43  import org.apache.hc.core5.http.HttpHost;
44  import org.apache.hc.core5.http.config.Lookup;
45  import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
46  import org.apache.hc.core5.reactor.ConnectionInitiator;
47  import org.apache.hc.core5.reactor.IOSession;
48  import org.apache.hc.core5.util.Args;
49  import org.apache.hc.core5.util.Timeout;
50  
51  final class DefaultAsyncClientConnectionOperator implements AsyncClientConnectionOperator {
52  
53      private final SchemePortResolver schemePortResolver;
54      private final MultihomeIOSessionRequester sessionRequester;
55      private final Lookup<TlsStrategy> tlsStrategyLookup;
56  
57      DefaultAsyncClientConnectionOperator(
58              final Lookup<TlsStrategy> tlsStrategyLookup,
59              final SchemePortResolver schemePortResolver,
60              final DnsResolver dnsResolver) {
61          this.tlsStrategyLookup = Args.notNull(tlsStrategyLookup, "TLS strategy lookup");
62          this.schemePortResolver = schemePortResolver != null ? schemePortResolver : DefaultSchemePortResolver.INSTANCE;
63          this.sessionRequester = new MultihomeIOSessionRequester(dnsResolver);
64      }
65  
66      @Override
67      public Future<ManagedAsyncClientConnection> connect(
68              final ConnectionInitiator connectionInitiator,
69              final HttpHost host,
70              final SocketAddress localAddress,
71              final Timeout connectTimeout,
72              final Object attachment,
73              final FutureCallback<ManagedAsyncClientConnection> callback) {
74          Args.notNull(connectionInitiator, "Connection initiator");
75          Args.notNull(host, "Host");
76          final ComplexFuture<ManagedAsyncClientConnection> future = new ComplexFuture<>(callback);
77          final HttpHost remoteEndpoint = RoutingSupport.normalize(host, schemePortResolver);
78          final InetAddress remoteAddress = host.getAddress();
79          final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(host.getSchemeName()) : null;
80          final Future<IOSession> sessionFuture = sessionRequester.connect(
81                  connectionInitiator,
82                  remoteEndpoint,
83                  remoteAddress != null ? new InetSocketAddress(remoteAddress, remoteEndpoint.getPort()) : null,
84                  localAddress,
85                  connectTimeout,
86                  attachment,
87                  new FutureCallback<IOSession>() {
88  
89                      @Override
90                      public void completed(final IOSession session) {
91                          final DefaultManagedAsyncClientConnectionyncClientConnection.html#DefaultManagedAsyncClientConnection">DefaultManagedAsyncClientConnection connection = new DefaultManagedAsyncClientConnection(session);
92                          if (tlsStrategy != null) {
93                              try {
94                                  tlsStrategy.upgrade(
95                                          connection,
96                                          host,
97                                          session.getLocalAddress(),
98                                          session.getRemoteAddress(),
99                                          attachment,
100                                         connectTimeout);
101                             } catch (final Exception ex) {
102                                 future.failed(ex);
103                                 return;
104                             }
105                         }
106                         future.completed(connection);
107                     }
108 
109                     @Override
110                     public void failed(final Exception ex) {
111                         future.failed(ex);
112                     }
113 
114                     @Override
115                     public void cancelled() {
116                         future.cancel();
117                     }
118 
119                 });
120         future.setDependency(sessionFuture);
121         return future;
122     }
123 
124     @Override
125     public void upgrade(final ManagedAsyncClientConnection connection, final HttpHost host, final Object attachment) {
126         final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(host.getSchemeName()) : null;
127         if (tlsStrategy != null) {
128             tlsStrategy.upgrade(
129                     connection,
130                     host,
131                     connection.getLocalAddress(),
132                     connection.getRemoteAddress(),
133                     attachment,
134                     null);
135         }
136 
137     }
138 }