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    *   https://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 io.netty.buffer.ByteBufAllocator;
19  
20  import javax.net.ssl.SSLEngine;
21  
22  /**
23   * The {@link JdkApplicationProtocolNegotiator} to use if you need ALPN and are using {@link SslProvider#JDK}.
24   *
25   * @deprecated use {@link ApplicationProtocolConfig}.
26   */
27  @Deprecated
28  public final class JdkAlpnApplicationProtocolNegotiator extends JdkBaseApplicationProtocolNegotiator {
29      private static final boolean AVAILABLE = Conscrypt.isAvailable() ||
30                                               JdkAlpnSslUtils.supportsAlpn() ||
31                                               BouncyCastle.isAvailable();
32  
33      private static final SslEngineWrapperFactory ALPN_WRAPPER = AVAILABLE ? new AlpnWrapper() : new FailureWrapper();
34  
35      /**
36       * Create a new instance.
37       * @param protocols The order of iteration determines the preference of support for protocols.
38       */
39      public JdkAlpnApplicationProtocolNegotiator(Iterable<String> protocols) {
40          this(false, protocols);
41      }
42  
43      /**
44       * Create a new instance.
45       * @param protocols The order of iteration determines the preference of support for protocols.
46       */
47      public JdkAlpnApplicationProtocolNegotiator(String... protocols) {
48          this(false, protocols);
49      }
50  
51      /**
52       * Create a new instance.
53       * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected.
54       * @param protocols The order of iteration determines the preference of support for protocols.
55       */
56      public JdkAlpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, Iterable<String> protocols) {
57          this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols);
58      }
59  
60      /**
61       * Create a new instance.
62       * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected.
63       * @param protocols The order of iteration determines the preference of support for protocols.
64       */
65      public JdkAlpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, String... protocols) {
66          this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols);
67      }
68  
69      /**
70       * Create a new instance.
71       * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected.
72       * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected.
73       * @param protocols The order of iteration determines the preference of support for protocols.
74       */
75      public JdkAlpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols,
76              boolean serverFailIfNoCommonProtocols, Iterable<String> protocols) {
77          this(serverFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY,
78                  clientFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY,
79                  protocols);
80      }
81  
82      /**
83       * Create a new instance.
84       * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected.
85       * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected.
86       * @param protocols The order of iteration determines the preference of support for protocols.
87       */
88      public JdkAlpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols,
89              boolean serverFailIfNoCommonProtocols, String... protocols) {
90          this(serverFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY,
91                  clientFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY,
92                  protocols);
93      }
94  
95      /**
96       * Create a new instance.
97       * @param selectorFactory The factory which provides classes responsible for selecting the protocol.
98       * @param listenerFactory The factory which provides to be notified of which protocol was selected.
99       * @param protocols The order of iteration determines the preference of support for protocols.
100      */
101     public JdkAlpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory,
102             ProtocolSelectionListenerFactory listenerFactory, Iterable<String> protocols) {
103         super(ALPN_WRAPPER, selectorFactory, listenerFactory, protocols);
104     }
105 
106     /**
107      * Create a new instance.
108      * @param selectorFactory The factory which provides classes responsible for selecting the protocol.
109      * @param listenerFactory The factory which provides to be notified of which protocol was selected.
110      * @param protocols The order of iteration determines the preference of support for protocols.
111      */
112     public JdkAlpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory,
113             ProtocolSelectionListenerFactory listenerFactory, String... protocols) {
114         super(ALPN_WRAPPER, selectorFactory, listenerFactory, protocols);
115     }
116 
117     private static final class FailureWrapper extends AllocatorAwareSslEngineWrapperFactory {
118         @Override
119         public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc,
120                                        JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
121             throw new RuntimeException("ALPN unsupported. Does your JDK version support it?"
122                     + " For Conscrypt, add the appropriate Conscrypt JAR to classpath and set the security provider.");
123         }
124     }
125 
126     private static final class AlpnWrapper extends AllocatorAwareSslEngineWrapperFactory {
127         @Override
128         public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc,
129                                        JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
130             if (Conscrypt.isEngineSupported(engine)) {
131                 return isServer ? ConscryptAlpnSslEngine.newServerEngine(engine, alloc, applicationNegotiator)
132                         : ConscryptAlpnSslEngine.newClientEngine(engine, alloc, applicationNegotiator);
133             }
134             if (BouncyCastle.isInUse(engine)) {
135                 return new BouncyCastleAlpnSslEngine(engine, applicationNegotiator, isServer);
136             }
137             // ALPN support was recently backported to Java8 as
138             // https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8230977.
139             // Because of this lets not do a Java version runtime check but just depend on if the required methods are
140             // present
141             if (JdkAlpnSslUtils.supportsAlpn()) {
142                 return new JdkAlpnSslEngine(engine, applicationNegotiator, isServer);
143             }
144             throw new UnsupportedOperationException("ALPN not supported. Unable to wrap SSLEngine of type '"
145                     + engine.getClass().getName() + "')");
146         }
147     }
148 
149     static boolean isAlpnSupported() {
150         return AVAILABLE;
151     }
152 }