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