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.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 }