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.io.IOException;
31  import java.net.SocketAddress;
32  import java.util.concurrent.atomic.AtomicBoolean;
33  
34  import javax.net.ssl.SSLContext;
35  import javax.net.ssl.SSLSession;
36  
37  import org.apache.hc.client5.http.nio.ManagedAsyncClientConnection;
38  import org.apache.hc.core5.concurrent.FutureCallback;
39  import org.apache.hc.core5.http.EndpointDetails;
40  import org.apache.hc.core5.http.HttpConnection;
41  import org.apache.hc.core5.http.HttpVersion;
42  import org.apache.hc.core5.http.ProtocolVersion;
43  import org.apache.hc.core5.http.nio.command.ShutdownCommand;
44  import org.apache.hc.core5.io.CloseMode;
45  import org.apache.hc.core5.net.NamedEndpoint;
46  import org.apache.hc.core5.reactor.Command;
47  import org.apache.hc.core5.reactor.IOEventHandler;
48  import org.apache.hc.core5.reactor.IOSession;
49  import org.apache.hc.core5.reactor.ProtocolIOSession;
50  import org.apache.hc.core5.reactor.ssl.SSLBufferMode;
51  import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
52  import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
53  import org.apache.hc.core5.reactor.ssl.TlsDetails;
54  import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
55  import org.apache.hc.core5.util.Identifiable;
56  import org.apache.hc.core5.util.Timeout;
57  import org.slf4j.Logger;
58  import org.slf4j.LoggerFactory;
59  
60  final class DefaultManagedAsyncClientConnection implements ManagedAsyncClientConnection, Identifiable {
61  
62      private static final Logger LOG = LoggerFactory.getLogger(DefaultManagedAsyncClientConnection.class);
63  
64      private final IOSession ioSession;
65      private final Timeout socketTimeout;
66      private final AtomicBoolean closed;
67  
68      public DefaultManagedAsyncClientConnection(final IOSession ioSession) {
69          this.ioSession = ioSession;
70          this.socketTimeout = ioSession.getSocketTimeout();
71          this.closed = new AtomicBoolean();
72      }
73  
74      @Override
75      public String getId() {
76          return ioSession.getId();
77      }
78  
79      @Override
80      public void close(final CloseMode closeMode) {
81          if (this.closed.compareAndSet(false, true)) {
82              if (LOG.isDebugEnabled()) {
83                  LOG.debug("{} Shutdown connection {}", getId(), closeMode);
84              }
85              ioSession.close(closeMode);
86          }
87      }
88  
89      @Override
90      public void close() throws IOException {
91          if (this.closed.compareAndSet(false, true)) {
92              if (LOG.isDebugEnabled()) {
93                  LOG.debug("{} Close connection", getId());
94              }
95              ioSession.enqueue(new ShutdownCommand(CloseMode.GRACEFUL), Command.Priority.IMMEDIATE);
96          }
97      }
98  
99      @Override
100     public boolean isOpen() {
101         final IOSession ioSession = this.ioSession;
102         if (ioSession.isOpen()) {
103             final IOEventHandler handler = ioSession.getHandler();
104             if (handler instanceof HttpConnection) {
105                 return ((HttpConnection) handler).isOpen();
106             }
107             return true;
108         } else {
109             return false;
110         }
111     }
112 
113     @Override
114     public void setSocketTimeout(final Timeout timeout) {
115         ioSession.setSocketTimeout(timeout);
116     }
117 
118     @Override
119     public Timeout getSocketTimeout() {
120         return ioSession.getSocketTimeout();
121     }
122 
123     @Override
124     public SocketAddress getRemoteAddress() {
125         return ioSession.getRemoteAddress();
126     }
127 
128     @Override
129     public SocketAddress getLocalAddress() {
130         return ioSession.getLocalAddress();
131     }
132 
133     @Override
134     public EndpointDetails getEndpointDetails() {
135         final IOEventHandler handler = ioSession.getHandler();
136         if (handler instanceof HttpConnection) {
137             return ((HttpConnection) handler).getEndpointDetails();
138         }
139         return null;
140     }
141 
142     @Override
143     public ProtocolVersion getProtocolVersion() {
144         final IOEventHandler handler = ioSession.getHandler();
145         if (handler instanceof HttpConnection) {
146             final ProtocolVersion version = ((HttpConnection) handler).getProtocolVersion();
147             if (version != null) {
148                 return version;
149             }
150         }
151         return HttpVersion.DEFAULT;
152     }
153 
154     @Override
155     public void startTls(
156             final SSLContext sslContext,
157             final NamedEndpoint endpoint,
158             final SSLBufferMode sslBufferMode,
159             final SSLSessionInitializer initializer,
160             final SSLSessionVerifier verifier,
161             final Timeout handshakeTimeout,
162             final FutureCallback<TransportSecurityLayer> callback) throws UnsupportedOperationException {
163         if (LOG.isDebugEnabled()) {
164             LOG.debug("{} start TLS", getId());
165         }
166         if (ioSession instanceof TransportSecurityLayer) {
167             ((TransportSecurityLayer) ioSession).startTls(sslContext, endpoint, sslBufferMode, initializer, verifier,
168                 handshakeTimeout, callback);
169         } else {
170             throw new UnsupportedOperationException("TLS upgrade not supported");
171         }
172     }
173 
174     @Override
175     public void startTls(
176             final SSLContext sslContext,
177             final NamedEndpoint endpoint,
178             final SSLBufferMode sslBufferMode,
179             final SSLSessionInitializer initializer,
180             final SSLSessionVerifier verifier,
181             final Timeout handshakeTimeout) throws UnsupportedOperationException {
182         startTls(sslContext, endpoint, sslBufferMode, initializer, verifier, handshakeTimeout, null);
183     }
184 
185     @Override
186     public TlsDetails getTlsDetails() {
187         return ioSession instanceof TransportSecurityLayer ? ((TransportSecurityLayer) ioSession).getTlsDetails() : null;
188     }
189 
190     @Override
191     public SSLSession getSSLSession() {
192         final TlsDetails tlsDetails = getTlsDetails();
193         return tlsDetails != null ? tlsDetails.getSSLSession() : null;
194     }
195 
196     @Override
197     public void submitCommand(final Command command, final Command.Priority priority) {
198         if (LOG.isDebugEnabled()) {
199             LOG.debug("{} {} with {} priority", getId(), command.getClass().getSimpleName(), priority);
200         }
201         ioSession.enqueue(command, Command.Priority.IMMEDIATE);
202     }
203 
204     @Override
205     public void passivate() {
206         ioSession.setSocketTimeout(Timeout.ZERO_MILLISECONDS);
207     }
208 
209     @Override
210     public void activate() {
211         ioSession.setSocketTimeout(socketTimeout);
212     }
213 
214     @Override
215     public void switchProtocol(final String protocolId,
216                                final FutureCallback<ProtocolIOSession> callback) throws UnsupportedOperationException {
217         if (ioSession instanceof ProtocolIOSession) {
218             ((ProtocolIOSession) ioSession).switchProtocol(protocolId, callback);
219         } else {
220             throw new UnsupportedOperationException("Protocol switch not supported");
221         }
222     }
223 
224 }