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.core5.http2.impl.nio;
29
30 import java.io.IOException;
31 import java.net.SocketAddress;
32 import java.nio.ByteBuffer;
33 import java.util.concurrent.atomic.AtomicBoolean;
34 import java.util.concurrent.atomic.AtomicReference;
35
36 import javax.net.ssl.SSLSession;
37
38 import org.apache.hc.core5.concurrent.FutureCallback;
39 import org.apache.hc.core5.http.ConnectionClosedException;
40 import org.apache.hc.core5.http.EndpointDetails;
41 import org.apache.hc.core5.http.ProtocolVersion;
42 import org.apache.hc.core5.http.impl.nio.HttpConnectionEventHandler;
43 import org.apache.hc.core5.http.nio.command.CommandSupport;
44 import org.apache.hc.core5.io.CloseMode;
45 import org.apache.hc.core5.io.SocketTimeoutExceptionFactory;
46 import org.apache.hc.core5.reactor.IOSession;
47 import org.apache.hc.core5.reactor.ProtocolIOSession;
48 import org.apache.hc.core5.reactor.ssl.TlsDetails;
49 import org.apache.hc.core5.util.Args;
50 import org.apache.hc.core5.util.Timeout;
51
52 abstract class ProtocolNegotiatorBase implements HttpConnectionEventHandler {
53
54 final ProtocolIOSession ioSession;
55 private final AtomicReference<HttpConnectionEventHandler> protocolHandlerRef;
56 private final FutureCallback<ProtocolIOSession> resultCallback;
57 private final AtomicBoolean completed;
58 private final AtomicReference<ProtocolVersion> negotiatedProtocolRef;
59
60 ProtocolNegotiatorBase(
61 final ProtocolIOSession ioSession,
62 final FutureCallback<ProtocolIOSession> resultCallback) {
63 this.ioSession = Args.notNull(ioSession, "I/O session");
64 this.protocolHandlerRef = new AtomicReference<>();
65 this.resultCallback = resultCallback;
66 this.completed = new AtomicBoolean();
67 this.negotiatedProtocolRef = new AtomicReference<>();
68 }
69
70 void startProtocol(final ProtocolVersion protocolVersion, final HttpConnectionEventHandler protocolHandler, final ByteBuffer data) throws IOException {
71 negotiatedProtocolRef.set(protocolVersion);
72 protocolHandlerRef.set(protocolHandler);
73 ioSession.upgrade(protocolHandler);
74 protocolHandler.connected(ioSession);
75 if (data != null && data.hasRemaining()) {
76 protocolHandler.inputReady(ioSession, data);
77 }
78 if (completed.compareAndSet(false, true) && resultCallback != null) {
79 resultCallback.completed(ioSession);
80 }
81 }
82
83 @Override
84 public void timeout(final IOSession session, final Timeout timeout) {
85 exception(session, SocketTimeoutExceptionFactory.create(timeout));
86 }
87
88 @Override
89 public void exception(final IOSession session, final Exception cause) {
90 final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.get();
91 try {
92 session.close(CloseMode.IMMEDIATE);
93 if (protocolHandler != null) {
94 protocolHandler.exception(session, cause);
95 } else {
96 CommandSupport.failCommands(session, cause);
97 }
98 } catch (final Exception ex) {
99 if (completed.compareAndSet(false, true) && resultCallback != null) {
100 resultCallback.failed(ex);
101 }
102 }
103 }
104
105 @Override
106 public void disconnected(final IOSession session) {
107 final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.getAndSet(null);
108 try {
109 if (protocolHandler != null) {
110 protocolHandler.disconnected(ioSession);
111 } else {
112 CommandSupport.cancelCommands(session);
113 }
114 } finally {
115 if (completed.compareAndSet(false, true) && resultCallback != null) {
116 resultCallback.failed(new ConnectionClosedException());
117 }
118 }
119 }
120
121 @Override
122 public SSLSession getSSLSession() {
123 final TlsDetails tlsDetails = ioSession.getTlsDetails();
124 return tlsDetails != null ? tlsDetails.getSSLSession() : null;
125 }
126
127 @Override
128 public EndpointDetails getEndpointDetails() {
129 return null;
130 }
131
132 @Override
133 public void setSocketTimeout(final Timeout timeout) {
134 ioSession.setSocketTimeout(timeout);
135 }
136
137 @Override
138 public Timeout getSocketTimeout() {
139 return ioSession.getSocketTimeout();
140 }
141
142 @Override
143 public ProtocolVersion getProtocolVersion() {
144 return negotiatedProtocolRef.get();
145 }
146
147 @Override
148 public SocketAddress getRemoteAddress() {
149 return ioSession.getRemoteAddress();
150 }
151
152 @Override
153 public SocketAddress getLocalAddress() {
154 return ioSession.getLocalAddress();
155 }
156
157 @Override
158 public boolean isOpen() {
159 return ioSession.isOpen();
160 }
161
162 @Override
163 public void close() throws IOException {
164 ioSession.close();
165 }
166
167 @Override
168 public void close(final CloseMode closeMode) {
169 ioSession.close(closeMode);
170 }
171
172 }