1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl;
17
18 import io.netty.util.internal.StringUtil;
19 import io.netty.util.internal.SuppressJava6Requirement;
20
21 import javax.net.ssl.SSLEngine;
22 import javax.net.ssl.SSLEngineResult;
23 import javax.net.ssl.SSLException;
24
25 import java.nio.ByteBuffer;
26 import java.util.LinkedHashSet;
27 import java.util.List;
28 import java.util.function.BiConsumer;
29 import java.util.function.BiFunction;
30
31 import static io.netty.handler.ssl.SslUtils.toSSLHandshakeException;
32 import static io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectionListener;
33 import static io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector;
34
35 @SuppressJava6Requirement(reason = "Usage guarded by java version check")
36 class JdkAlpnSslEngine extends JdkSslEngine {
37 private final ProtocolSelectionListener selectionListener;
38 private final AlpnSelector alpnSelector;
39
40 final class AlpnSelector implements BiFunction<SSLEngine, List<String>, String> {
41 private final ProtocolSelector selector;
42 private boolean called;
43
44 AlpnSelector(ProtocolSelector selector) {
45 this.selector = selector;
46 }
47
48 @Override
49 public String apply(SSLEngine sslEngine, List<String> strings) {
50 assert !called;
51 called = true;
52
53 try {
54 String selected = selector.select(strings);
55 return selected == null ? StringUtil.EMPTY_STRING : selected;
56 } catch (Exception cause) {
57
58
59
60
61 return null;
62 }
63 }
64
65 void checkUnsupported() {
66 if (called) {
67
68
69
70
71 return;
72 }
73 String protocol = getApplicationProtocol();
74 assert protocol != null;
75
76 if (protocol.isEmpty()) {
77
78 selector.unsupported();
79 }
80 }
81 }
82
83 JdkAlpnSslEngine(SSLEngine engine,
84 @SuppressWarnings("deprecation") JdkApplicationProtocolNegotiator applicationNegotiator,
85 boolean isServer, BiConsumer<SSLEngine, AlpnSelector> setHandshakeApplicationProtocolSelector,
86 BiConsumer<SSLEngine, List<String>> setApplicationProtocols) {
87 super(engine);
88 if (isServer) {
89 selectionListener = null;
90 alpnSelector = new AlpnSelector(applicationNegotiator.protocolSelectorFactory().
91 newSelector(this, new LinkedHashSet<String>(applicationNegotiator.protocols())));
92 setHandshakeApplicationProtocolSelector.accept(engine, alpnSelector);
93 } else {
94 selectionListener = applicationNegotiator.protocolListenerFactory()
95 .newListener(this, applicationNegotiator.protocols());
96 alpnSelector = null;
97 setApplicationProtocols.accept(engine, applicationNegotiator.protocols());
98 }
99 }
100
101 JdkAlpnSslEngine(SSLEngine engine,
102 @SuppressWarnings("deprecation") JdkApplicationProtocolNegotiator applicationNegotiator,
103 boolean isServer) {
104 this(engine, applicationNegotiator, isServer,
105 new BiConsumer<SSLEngine, AlpnSelector>() {
106 @Override
107 public void accept(SSLEngine e, AlpnSelector s) {
108 JdkAlpnSslUtils.setHandshakeApplicationProtocolSelector(e, s);
109 }
110 },
111 new BiConsumer<SSLEngine, List<String>>() {
112 @Override
113 public void accept(SSLEngine e, List<String> p) {
114 JdkAlpnSslUtils.setApplicationProtocols(e, p);
115 }
116 });
117 }
118
119 private SSLEngineResult verifyProtocolSelection(SSLEngineResult result) throws SSLException {
120 if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED) {
121 if (alpnSelector == null) {
122
123 try {
124 String protocol = getApplicationProtocol();
125 assert protocol != null;
126 if (protocol.isEmpty()) {
127
128
129
130
131 selectionListener.unsupported();
132 } else {
133 selectionListener.selected(protocol);
134 }
135 } catch (Throwable e) {
136 throw toSSLHandshakeException(e);
137 }
138 } else {
139 assert selectionListener == null;
140 alpnSelector.checkUnsupported();
141 }
142 }
143 return result;
144 }
145
146 @Override
147 public SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
148 return verifyProtocolSelection(super.wrap(src, dst));
149 }
150
151 @Override
152 public SSLEngineResult wrap(ByteBuffer[] srcs, ByteBuffer dst) throws SSLException {
153 return verifyProtocolSelection(super.wrap(srcs, dst));
154 }
155
156 @Override
157 public SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int len, ByteBuffer dst) throws SSLException {
158 return verifyProtocolSelection(super.wrap(srcs, offset, len, dst));
159 }
160
161 @Override
162 public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
163 return verifyProtocolSelection(super.unwrap(src, dst));
164 }
165
166 @Override
167 public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
168 return verifyProtocolSelection(super.unwrap(src, dsts));
169 }
170
171 @Override
172 public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dst, int offset, int len) throws SSLException {
173 return verifyProtocolSelection(super.unwrap(src, dst, offset, len));
174 }
175
176 @Override
177 void setNegotiatedApplicationProtocol(String applicationProtocol) {
178
179 }
180
181 @Override
182 public String getNegotiatedApplicationProtocol() {
183 String protocol = getApplicationProtocol();
184 if (protocol != null) {
185 return protocol.isEmpty() ? null : protocol;
186 }
187 return null;
188 }
189
190
191
192 public String getApplicationProtocol() {
193 return JdkAlpnSslUtils.getApplicationProtocol(getWrappedEngine());
194 }
195
196 public String getHandshakeApplicationProtocol() {
197 return JdkAlpnSslUtils.getHandshakeApplicationProtocol(getWrappedEngine());
198 }
199
200 public void setHandshakeApplicationProtocolSelector(BiFunction<SSLEngine, List<String>, String> selector) {
201 JdkAlpnSslUtils.setHandshakeApplicationProtocolSelector(getWrappedEngine(), selector);
202 }
203
204 public BiFunction<SSLEngine, List<String>, String> getHandshakeApplicationProtocolSelector() {
205 return JdkAlpnSslUtils.getHandshakeApplicationProtocolSelector(getWrappedEngine());
206 }
207 }