diff --git a/netty/src/main/java/io/grpc/transport/netty/JettyAlpnVerifier.java b/netty/src/main/java/io/grpc/transport/netty/JettyAlpnVerifier.java new file mode 100644 index 0000000000..9f0fbf37a2 --- /dev/null +++ b/netty/src/main/java/io/grpc/transport/netty/JettyAlpnVerifier.java @@ -0,0 +1,62 @@ +/* + * Copyright 2015, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.transport.netty; + +/** + * Utility class that verifies that Jetty ALPN is properly configured for the system. + */ +final class JettyAlpnVerifier { + private JettyAlpnVerifier() { + } + + /** + * Exception thrown when Jetty ALPN was not found in the boot classloader. + */ + static final class NotFoundException extends Exception { + public NotFoundException(Throwable cause) { + super("Jetty ALPN not found in boot classloader.", cause); + } + } + + /** + * Verifies that Jetty ALPN is configured properly on this system. + * @throws NotFoundException thrown if Jetty ALPN is missing from the boot classloader. + */ + static void verifyJettyAlpn() throws NotFoundException { + try { + // Check the boot classloader for the ALPN class. + Class.forName("org.eclipse.jetty.alpn.ALPN", true, null); + } catch (ClassNotFoundException e) { + throw new NotFoundException(e); + } + } +} diff --git a/netty/src/main/java/io/grpc/transport/netty/ProtocolNegotiators.java b/netty/src/main/java/io/grpc/transport/netty/ProtocolNegotiators.java index 055d61565c..56064e41d6 100644 --- a/netty/src/main/java/io/grpc/transport/netty/ProtocolNegotiators.java +++ b/netty/src/main/java/io/grpc/transport/netty/ProtocolNegotiators.java @@ -48,6 +48,8 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http2.Http2ClientUpgradeCodec; import io.netty.handler.codec.http2.Http2ConnectionHandler; +import io.netty.handler.ssl.OpenSslContext; +import io.netty.handler.ssl.OpenSslEngine; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.SslHandshakeCompletionEvent; @@ -78,6 +80,16 @@ public final class ProtocolNegotiators { */ public static ChannelHandler serverTls(SSLEngine sslEngine) { Preconditions.checkNotNull(sslEngine, "sslEngine"); + + // If we're using Jetty ALPN, verify that it is configured properly. + if (!(sslEngine instanceof OpenSslEngine)) { + try { + JettyAlpnVerifier.verifyJettyAlpn(); + } catch (JettyAlpnVerifier.NotFoundException e) { + throw new IllegalArgumentException(e); + } + } + return new SslHandler(sslEngine, false); } @@ -91,6 +103,15 @@ public final class ProtocolNegotiators { Preconditions.checkNotNull(sslContext, "sslContext"); Preconditions.checkNotNull(inetAddress, "inetAddress"); + // If we're using Jetty ALPN, verify that it is configured properly. + if (!(sslContext instanceof OpenSslContext)) { + try { + JettyAlpnVerifier.verifyJettyAlpn(); + } catch (JettyAlpnVerifier.NotFoundException e) { + throw new IllegalArgumentException(e); + } + } + return new ProtocolNegotiator() { @Override public Handler newHandler(Http2ConnectionHandler handler) {