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
59 ProtocolNegotiatorBase(
60 final ProtocolIOSession ioSession,
61 final FutureCallback<ProtocolIOSession> resultCallback) {
62 this.ioSession = Args.notNull(ioSession, "I/O session");
63 this.protocolHandlerRef = new AtomicReference<>();
64 this.resultCallback = resultCallback;
65 this.completed = new AtomicBoolean();
66 }
67
68 void startProtocol(final HttpConnectionEventHandler protocolHandler, final ByteBuffer data) throws IOException {
69 protocolHandlerRef.set(protocolHandler);
70 ioSession.upgrade(protocolHandler);
71 protocolHandler.connected(ioSession);
72 if (data != null && data.hasRemaining()) {
73 protocolHandler.inputReady(ioSession, data);
74 }
75 if (completed.compareAndSet(false, true) && resultCallback != null) {
76 resultCallback.completed(ioSession);
77 }
78 }
79
80 @Override
81 public void timeout(final IOSession session, final Timeout timeout) {
82 exception(session, SocketTimeoutExceptionFactory.create(timeout));
83 }
84
85 @Override
86 public void exception(final IOSession session, final Exception cause) {
87 final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.get();
88 try {
89 session.close(CloseMode.IMMEDIATE);
90 if (protocolHandler != null) {
91 protocolHandler.exception(session, cause);
92 } else {
93 CommandSupport.failCommands(session, cause);
94 }
95 } catch (final Exception ex) {
96 if (completed.compareAndSet(false, true) && resultCallback != null) {
97 resultCallback.failed(ex);
98 }
99 }
100 }
101
102 @Override
103 public void disconnected(final IOSession session) {
104 final HttpConnectionEventHandler protocolHandler = protocolHandlerRef.getAndSet(null);
105 try {
106 if (protocolHandler != null) {
107 protocolHandler.disconnected(ioSession);
108 } else {
109 CommandSupport.cancelCommands(session);
110 }
111 } finally {
112 if (completed.compareAndSet(false, true) && resultCallback != null) {
113 resultCallback.failed(new ConnectionClosedException());
114 }
115 }
116 }
117
118 @Override
119 public SSLSession getSSLSession() {
120 final TlsDetails tlsDetails = ioSession.getTlsDetails();
121 return tlsDetails != null ? tlsDetails.getSSLSession() : null;
122 }
123
124 @Override
125 public EndpointDetails getEndpointDetails() {
126 return null;
127 }
128
129 @Override
130 public void setSocketTimeout(final Timeout timeout) {
131 ioSession.setSocketTimeout(timeout);
132 }
133
134 @Override
135 public Timeout getSocketTimeout() {
136 return ioSession.getSocketTimeout();
137 }
138
139 @Override
140 public ProtocolVersion getProtocolVersion() {
141 return null;
142 }
143
144 @Override
145 public SocketAddress getRemoteAddress() {
146 return ioSession.getRemoteAddress();
147 }
148
149 @Override
150 public SocketAddress getLocalAddress() {
151 return ioSession.getLocalAddress();
152 }
153
154 @Override
155 public boolean isOpen() {
156 return ioSession.isOpen();
157 }
158
159 @Override
160 public void close() throws IOException {
161 ioSession.close();
162 }
163
164 @Override
165 public void close(final CloseMode closeMode) {
166 ioSession.close(closeMode);
167 }
168
169 }