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