1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl;
17
18 import static io.netty.handler.ssl.SslUtils.toSSLHandshakeException;
19 import static io.netty.util.internal.ObjectUtil.checkNotNull;
20
21 import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectionListener;
22 import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector;
23
24 import java.util.LinkedHashSet;
25 import java.util.List;
26
27 import javax.net.ssl.SSLEngine;
28 import javax.net.ssl.SSLException;
29
30 import io.netty.util.internal.PlatformDependent;
31 import org.eclipse.jetty.alpn.ALPN;
32
33 abstract class JettyAlpnSslEngine extends JdkSslEngine {
34 private static final boolean available = initAvailable();
35
36 static boolean isAvailable() {
37 return available;
38 }
39
40 private static boolean initAvailable() {
41 if (PlatformDependent.javaVersion() <= 8) {
42 try {
43
44 Class.forName("sun.security.ssl.ALPNExtension", true, null);
45 return true;
46 } catch (Throwable ignore) {
47
48 }
49 }
50 return false;
51 }
52
53 static JettyAlpnSslEngine newClientEngine(SSLEngine engine,
54 JdkApplicationProtocolNegotiator applicationNegotiator) {
55 return new ClientEngine(engine, applicationNegotiator);
56 }
57
58 static JettyAlpnSslEngine newServerEngine(SSLEngine engine,
59 JdkApplicationProtocolNegotiator applicationNegotiator) {
60 return new ServerEngine(engine, applicationNegotiator);
61 }
62
63 private JettyAlpnSslEngine(SSLEngine engine) {
64 super(engine);
65 }
66
67 private static final class ClientEngine extends JettyAlpnSslEngine {
68 ClientEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator) {
69 super(engine);
70 checkNotNull(applicationNegotiator, "applicationNegotiator");
71 final ProtocolSelectionListener protocolListener = checkNotNull(applicationNegotiator
72 .protocolListenerFactory().newListener(this, applicationNegotiator.protocols()),
73 "protocolListener");
74 ALPN.put(engine, new ALPN.ClientProvider() {
75 @Override
76 public List<String> protocols() {
77 return applicationNegotiator.protocols();
78 }
79
80 @Override
81 public void selected(String protocol) throws SSLException {
82 try {
83 protocolListener.selected(protocol);
84 } catch (Throwable t) {
85 throw toSSLHandshakeException(t);
86 }
87 }
88
89 @Override
90 public void unsupported() {
91 protocolListener.unsupported();
92 }
93 });
94 }
95
96 @Override
97 public void closeInbound() throws SSLException {
98 try {
99 ALPN.remove(getWrappedEngine());
100 } finally {
101 super.closeInbound();
102 }
103 }
104
105 @Override
106 public void closeOutbound() {
107 try {
108 ALPN.remove(getWrappedEngine());
109 } finally {
110 super.closeOutbound();
111 }
112 }
113 }
114
115 private static final class ServerEngine extends JettyAlpnSslEngine {
116 ServerEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator) {
117 super(engine);
118 checkNotNull(applicationNegotiator, "applicationNegotiator");
119 final ProtocolSelector protocolSelector = checkNotNull(applicationNegotiator.protocolSelectorFactory()
120 .newSelector(this, new LinkedHashSet<String>(applicationNegotiator.protocols())),
121 "protocolSelector");
122 ALPN.put(engine, new ALPN.ServerProvider() {
123 @Override
124 public String select(List<String> protocols) throws SSLException {
125 try {
126 return protocolSelector.select(protocols);
127 } catch (Throwable t) {
128 throw toSSLHandshakeException(t);
129 }
130 }
131
132 @Override
133 public void unsupported() {
134 protocolSelector.unsupported();
135 }
136 });
137 }
138
139 @Override
140 public void closeInbound() throws SSLException {
141 try {
142 ALPN.remove(getWrappedEngine());
143 } finally {
144 super.closeInbound();
145 }
146 }
147
148 @Override
149 public void closeOutbound() {
150 try {
151 ALPN.remove(getWrappedEngine());
152 } finally {
153 super.closeOutbound();
154 }
155 }
156 }
157 }