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