View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
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                  // Always use bootstrap class loader.
44                  Class.forName("sun.security.ssl.ALPNExtension", true, null);
45                  return true;
46              } catch (Throwable ignore) {
47                  // alpn-boot was not loaded.
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 }