Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5fe7388

Browse files
author
Nathan Mittler
committed
Merge pull request grpc#678 from nmittler/npn
Adding support for NPN fallback.
2 parents 46c76bd + 247ffb1 commit 5fe7388

File tree

10 files changed

+148
-55
lines changed

10 files changed

+148
-55
lines changed

benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import static io.grpc.benchmarks.qps.ClientConfiguration.ClientParam.TESTCA;
4545
import static io.grpc.benchmarks.qps.ClientConfiguration.ClientParam.TLS;
4646
import static io.grpc.benchmarks.qps.ClientConfiguration.ClientParam.TRANSPORT;
47+
import static io.grpc.benchmarks.qps.ClientConfiguration.ClientParam.USE_DEFAULT_CIPHERS;
4748
import static io.grpc.benchmarks.qps.ClientConfiguration.ClientParam.WARMUP_DURATION;
4849
import static io.grpc.benchmarks.qps.Utils.HISTOGRAM_MAX_VALUE;
4950
import static io.grpc.benchmarks.qps.Utils.HISTOGRAM_PRECISION;
@@ -325,7 +326,7 @@ private static void shutdown(List<Channel> channels) {
325326
public static void main(String... args) throws Exception {
326327
ClientConfiguration.Builder configBuilder = ClientConfiguration.newBuilder(
327328
ADDRESS, CHANNELS, OUTSTANDING_RPCS, CLIENT_PAYLOAD, SERVER_PAYLOAD,
328-
TLS, TESTCA, TRANSPORT, DURATION, WARMUP_DURATION, DIRECTEXECUTOR,
329+
TLS, TESTCA, USE_DEFAULT_CIPHERS, TRANSPORT, DURATION, WARMUP_DURATION, DIRECTEXECUTOR,
329330
SAVE_HISTOGRAM, STREAMING_RPCS, FLOW_CONTROL_WINDOW);
330331
ClientConfiguration config;
331332
try {

benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncServer.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import io.netty.channel.nio.NioEventLoopGroup;
5151
import io.netty.channel.socket.nio.NioServerSocketChannel;
5252
import io.netty.handler.ssl.SslContext;
53+
import io.netty.handler.ssl.SslContextBuilder;
5354
import io.netty.handler.ssl.SslProvider;
5455

5556
import java.io.File;
@@ -107,10 +108,17 @@ static ServerImpl newServer(ServerConfiguration config) throws IOException {
107108

108109
File cert = TestUtils.loadCert("server1.pem");
109110
File key = TestUtils.loadCert("server1.key");
110-
boolean useJdkSsl = config.transport == ServerConfiguration.Transport.NETTY_NIO;
111-
sslContext = GrpcSslContexts.forServer(cert, key)
112-
.sslProvider(useJdkSsl ? SslProvider.JDK : SslProvider.OPENSSL)
113-
.build();
111+
SslContextBuilder sslContextBuilder = GrpcSslContexts.forServer(cert, key);
112+
if (config.transport == ServerConfiguration.Transport.NETTY_NIO) {
113+
sslContextBuilder = GrpcSslContexts.configure(sslContextBuilder, SslProvider.JDK);
114+
} else {
115+
// Native transport with OpenSSL
116+
sslContextBuilder = GrpcSslContexts.configure(sslContextBuilder, SslProvider.OPENSSL);
117+
}
118+
if (config.useDefaultCiphers) {
119+
sslContextBuilder.ciphers(null);
120+
}
121+
sslContext = sslContextBuilder.build();
114122
}
115123

116124
final EventLoopGroup boss;

benchmarks/src/main/java/io/grpc/benchmarks/qps/ClientConfiguration.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class ClientConfiguration implements Configuration {
6060
Transport transport = Transport.NETTY_NIO;
6161
boolean tls;
6262
boolean testca;
63+
boolean useDefaultCiphers;
6364
boolean directExecutor;
6465
SocketAddress address;
6566
int channels = 4;
@@ -233,6 +234,13 @@ protected void setClientValue(ClientConfiguration config, String value) {
233234
config.testca = parseBoolean(value);
234235
}
235236
},
237+
USE_DEFAULT_CIPHERS("", "Use the default JDK ciphers for TLS (Used to support Java 7).",
238+
"" + DEFAULT.useDefaultCiphers) {
239+
@Override
240+
protected void setClientValue(ClientConfiguration config, String value) {
241+
config.useDefaultCiphers = parseBoolean(value);
242+
}
243+
},
236244
TRANSPORT("STR", Transport.getDescriptionString(), DEFAULT.transport.name().toLowerCase()) {
237245
@Override
238246
protected void setClientValue(ClientConfiguration config, String value) {

benchmarks/src/main/java/io/grpc/benchmarks/qps/OpenLoopClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import static io.grpc.benchmarks.qps.ClientConfiguration.ClientParam.TESTCA;
4343
import static io.grpc.benchmarks.qps.ClientConfiguration.ClientParam.TLS;
4444
import static io.grpc.benchmarks.qps.ClientConfiguration.ClientParam.TRANSPORT;
45+
import static io.grpc.benchmarks.qps.ClientConfiguration.ClientParam.USE_DEFAULT_CIPHERS;
4546
import static io.grpc.benchmarks.qps.Utils.HISTOGRAM_MAX_VALUE;
4647
import static io.grpc.benchmarks.qps.Utils.HISTOGRAM_PRECISION;
4748
import static io.grpc.benchmarks.qps.Utils.newClientChannel;
@@ -85,7 +86,7 @@ public OpenLoopClient(ClientConfiguration config) {
8586
public static void main(String... args) throws Exception {
8687
ClientConfiguration.Builder configBuilder = ClientConfiguration.newBuilder(
8788
ADDRESS, TARGET_QPS, CLIENT_PAYLOAD, SERVER_PAYLOAD, TLS,
88-
TESTCA, TRANSPORT, DURATION, SAVE_HISTOGRAM, FLOW_CONTROL_WINDOW);
89+
TESTCA, USE_DEFAULT_CIPHERS, TRANSPORT, DURATION, SAVE_HISTOGRAM, FLOW_CONTROL_WINDOW);
8990
ClientConfiguration config;
9091
try {
9192
config = configBuilder.build(args);

benchmarks/src/main/java/io/grpc/benchmarks/qps/ServerConfiguration.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class ServerConfiguration implements Configuration {
5555

5656
Transport transport = Transport.NETTY_NIO;
5757
boolean tls;
58+
boolean useDefaultCiphers;
5859
boolean directExecutor;
5960
SocketAddress address;
6061
int flowControlWindow = NettyChannelBuilder.DEFAULT_FLOW_CONTROL_WINDOW;
@@ -172,6 +173,13 @@ protected void setServerValue(ServerConfiguration config, String value) {
172173
config.tls = parseBoolean(value);
173174
}
174175
},
176+
USE_DEFAULT_CIPHERS("", "Use the default JDK ciphers for TLS (Used to support Java 7).",
177+
"false") {
178+
@Override
179+
protected void setServerValue(ServerConfiguration config, String value) {
180+
config.useDefaultCiphers = parseBoolean(value);
181+
}
182+
},
175183
TRANSPORT("STR", Transport.getDescriptionString(), DEFAULT.transport.name().toLowerCase()) {
176184
@Override
177185
protected void setServerValue(ServerConfiguration config, String value) {

benchmarks/src/main/java/io/grpc/benchmarks/qps/Utils.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import io.netty.channel.socket.nio.NioSocketChannel;
5151
import io.netty.channel.unix.DomainSocketAddress;
5252
import io.netty.handler.ssl.SslContext;
53+
import io.netty.handler.ssl.SslContextBuilder;
5354
import io.netty.handler.ssl.SslProvider;
5455

5556
import org.HdrHistogram.Histogram;
@@ -153,14 +154,21 @@ static Channel newClientChannel(ClientConfiguration config) throws IOException {
153154
}
154155

155156
// It's a Netty transport.
156-
SslContext context = null;
157+
SslContext sslContext = null;
157158
NegotiationType negotiationType = config.tls ? NegotiationType.TLS : NegotiationType.PLAINTEXT;
158159
if (config.tls && config.testca) {
159160
File cert = TestUtils.loadCert("ca.pem");
160-
boolean useJdkSsl = config.transport == ClientConfiguration.Transport.NETTY_NIO;
161-
context = GrpcSslContexts.forClient().trustManager(cert)
162-
.sslProvider(useJdkSsl ? SslProvider.JDK : SslProvider.OPENSSL)
163-
.build();
161+
SslContextBuilder sslContextBuilder = GrpcSslContexts.forClient().trustManager(cert);
162+
if (config.transport == ClientConfiguration.Transport.NETTY_NIO) {
163+
sslContextBuilder = GrpcSslContexts.configure(sslContextBuilder, SslProvider.JDK);
164+
} else {
165+
// Native transport with OpenSSL
166+
sslContextBuilder = GrpcSslContexts.configure(sslContextBuilder, SslProvider.OPENSSL);
167+
}
168+
if (config.useDefaultCiphers) {
169+
sslContextBuilder.ciphers(null);
170+
}
171+
sslContext = sslContextBuilder.build();
164172
}
165173
final EventLoopGroup group;
166174
final Class<? extends io.netty.channel.Channel> channelType;
@@ -192,7 +200,7 @@ static Channel newClientChannel(ClientConfiguration config) throws IOException {
192200
.channelType(channelType)
193201
.negotiationType(negotiationType)
194202
.executor(config.directExecutor ? MoreExecutors.newDirectExecutorService() : null)
195-
.sslContext(context)
203+
.sslContext(sslContext)
196204
.flowControlWindow(config.flowControlWindow)
197205
.build();
198206
}

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ subprojects {
145145
// on the Java version.
146146
def alpnboot_version = '8.1.2.v20141202'
147147
if (JavaVersion.current().ordinal() < JavaVersion.VERSION_1_8.ordinal()) {
148-
alpnboot_version = '7.1.2.v20141202'
148+
alpnboot_version = '7.1.3.v20150130'
149149
}
150150

151151
alpnboot_package_name = 'org.mortbay.jetty.alpn:alpn-boot:' + alpnboot_version

netty/src/main/java/io/grpc/netty/GrpcSslContexts.java

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131

3232
package io.grpc.netty;
3333

34+
import io.grpc.internal.ExperimentalApi;
3435
import io.netty.handler.codec.http2.Http2SecurityUtil;
3536
import io.netty.handler.ssl.ApplicationProtocolConfig;
3637
import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
3738
import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
3839
import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
3940
import io.netty.handler.ssl.SslContextBuilder;
41+
import io.netty.handler.ssl.SslProvider;
4042
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
4143

4244
import java.io.File;
@@ -47,11 +49,25 @@
4749
public class GrpcSslContexts {
4850
private GrpcSslContexts() {}
4951

50-
private static ApplicationProtocolConfig DEFAULT_APN = new ApplicationProtocolConfig(
51-
Protocol.ALPN,
52-
SelectorFailureBehavior.FATAL_ALERT,
53-
SelectedListenerFailureBehavior.FATAL_ALERT,
54-
"h2");
52+
private static String[] HTTP2_VERSIONS = {"h2"};
53+
54+
private static ApplicationProtocolConfig ALPN = new ApplicationProtocolConfig(
55+
Protocol.ALPN,
56+
SelectorFailureBehavior.FATAL_ALERT,
57+
SelectedListenerFailureBehavior.FATAL_ALERT,
58+
HTTP2_VERSIONS);
59+
60+
private static ApplicationProtocolConfig NPN = new ApplicationProtocolConfig(
61+
Protocol.NPN,
62+
SelectorFailureBehavior.FATAL_ALERT,
63+
SelectedListenerFailureBehavior.FATAL_ALERT,
64+
HTTP2_VERSIONS);
65+
66+
private static ApplicationProtocolConfig NPN_AND_ALPN = new ApplicationProtocolConfig(
67+
Protocol.NPN_AND_ALPN,
68+
SelectorFailureBehavior.FATAL_ALERT,
69+
SelectedListenerFailureBehavior.FATAL_ALERT,
70+
HTTP2_VERSIONS);
5571

5672
/**
5773
* Creates a SslContextBuilder with ciphers and APN appropriate for gRPC.
@@ -89,7 +105,59 @@ public static SslContextBuilder forServer(
89105
* an application requires particular settings it should override the options set here.
90106
*/
91107
public static SslContextBuilder configure(SslContextBuilder builder) {
92-
return builder.ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE)
93-
.applicationProtocolConfig(DEFAULT_APN);
108+
return configure(builder, defaultSslProvider());
109+
}
110+
111+
/**
112+
* Set ciphers and APN appropriate for gRPC. Precisely what is set is permitted to change, so if
113+
* an application requires particular settings it should override the options set here.
114+
*/
115+
@ExperimentalApi
116+
public static SslContextBuilder configure(SslContextBuilder builder, SslProvider provider) {
117+
return builder.sslProvider(provider)
118+
.ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE)
119+
.applicationProtocolConfig(selectApplicationProtocolConfig(provider));
120+
}
121+
122+
/**
123+
* Returns OpenSSL if available, otherwise returns the JDK provider.
124+
*/
125+
private static SslProvider defaultSslProvider() {
126+
return SslProvider.JDK;
127+
// TODO(nmittler): use this once we support OpenSSL.
128+
// return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK;
129+
}
130+
131+
/**
132+
* Attempts to select the best {@link ApplicationProtocolConfig} for the given
133+
* {@link SslProvider}.
134+
*/
135+
private static ApplicationProtocolConfig selectApplicationProtocolConfig(SslProvider provider) {
136+
switch (provider) {
137+
case JDK: {
138+
if (JettyTlsUtil.isJettyAlpnConfigured()) {
139+
return ALPN;
140+
}
141+
if (JettyTlsUtil.isJettyNpnConfigured()) {
142+
return NPN;
143+
}
144+
throw new IllegalArgumentException("Jetty ALPN/NPN has not been properly configured.");
145+
}
146+
case OPENSSL: {
147+
throw new IllegalArgumentException("OpenSSL is not currently supported.");
148+
// TODO(nmittler): use this once we support OpenSSL.
149+
/*if (!OpenSsl.isAvailable()) {
150+
throw new IllegalArgumentException("OpenSSL is not installed on the system.");
151+
}
152+
153+
if (OpenSsl.isAlpnSupported()) {
154+
return NPN_AND_ALPN;
155+
} else {
156+
return NPN;
157+
}*/
158+
}
159+
default:
160+
throw new IllegalArgumentException("Unsupported provider: " + provider);
161+
}
94162
}
95163
}

netty/src/main/java/io/grpc/netty/JettyAlpnVerifier.java renamed to netty/src/main/java/io/grpc/netty/JettyTlsUtil.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,31 +32,33 @@
3232
package io.grpc.netty;
3333

3434
/**
35-
* Utility class that verifies that Jetty ALPN is properly configured for the system.
35+
* Utility class for determining support for Jetty TLS ALPN/NPN.
3636
*/
37-
final class JettyAlpnVerifier {
38-
private JettyAlpnVerifier() {
37+
final class JettyTlsUtil {
38+
private JettyTlsUtil() {
3939
}
4040

4141
/**
42-
* Exception thrown when Jetty ALPN was not found in the boot classloader.
42+
* Indicates whether or not the Jetty ALPN jar is installed in the boot classloader.
4343
*/
44-
static final class NotFoundException extends Exception {
45-
public NotFoundException(Throwable cause) {
46-
super("Jetty ALPN not found in boot classloader.", cause);
44+
static boolean isJettyAlpnConfigured() {
45+
try {
46+
Class.forName("org.eclipse.jetty.alpn.ALPN", true, null);
47+
return true;
48+
} catch (ClassNotFoundException e) {
49+
return false;
4750
}
4851
}
4952

5053
/**
51-
* Verifies that Jetty ALPN is configured properly on this system.
52-
* @throws NotFoundException thrown if Jetty ALPN is missing from the boot classloader.
54+
* Indicates whether or not the Jetty NPN jar is installed in the boot classloader.
5355
*/
54-
static void verifyJettyAlpn() throws NotFoundException {
56+
static boolean isJettyNpnConfigured() {
5557
try {
56-
// Check the boot classloader for the ALPN class.
57-
Class.forName("org.eclipse.jetty.alpn.ALPN", true, null);
58+
Class.forName("org.eclipse.jetty.npn.NextProtoNego", true, null);
59+
return true;
5860
} catch (ClassNotFoundException e) {
59-
throw new NotFoundException(e);
61+
return false;
6062
}
6163
}
6264
}

netty/src/main/java/io/grpc/netty/ProtocolNegotiators.java

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
import io.netty.handler.codec.http2.Http2ClientUpgradeCodec;
4949
import io.netty.handler.codec.http2.Http2ConnectionHandler;
5050
import io.netty.handler.ssl.OpenSslContext;
51-
import io.netty.handler.ssl.OpenSslEngine;
5251
import io.netty.handler.ssl.SslContext;
5352
import io.netty.handler.ssl.SslHandler;
5453
import io.netty.handler.ssl.SslHandshakeCompletionEvent;
@@ -74,15 +73,6 @@ private ProtocolNegotiators() {
7473
public static ChannelHandler serverTls(SSLEngine sslEngine) {
7574
Preconditions.checkNotNull(sslEngine, "sslEngine");
7675

77-
// If we're using Jetty ALPN, verify that it is configured properly.
78-
if (!(sslEngine instanceof OpenSslEngine)) {
79-
try {
80-
JettyAlpnVerifier.verifyJettyAlpn();
81-
} catch (JettyAlpnVerifier.NotFoundException e) {
82-
throw new IllegalArgumentException(e);
83-
}
84-
}
85-
8676
return new SslHandler(sslEngine, false);
8777
}
8878

@@ -96,24 +86,23 @@ public static ProtocolNegotiator tls(final SslContext sslContext,
9686
Preconditions.checkNotNull(sslContext, "sslContext");
9787
Preconditions.checkNotNull(inetAddress, "inetAddress");
9888

99-
// If we're using Jetty ALPN, verify that it is configured properly.
100-
if (!(sslContext instanceof OpenSslContext)) {
101-
try {
102-
JettyAlpnVerifier.verifyJettyAlpn();
103-
} catch (JettyAlpnVerifier.NotFoundException e) {
104-
throw new IllegalArgumentException(e);
105-
}
106-
}
107-
10889
return new ProtocolNegotiator() {
10990
@Override
11091
public Handler newHandler(Http2ConnectionHandler handler) {
11192
ChannelHandler sslBootstrap = new ChannelHandlerAdapter() {
11293
@Override
11394
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
114-
// TODO(nmittler): Unsupported for OpenSSL in Netty < 4.1.Beta6.
115-
SSLEngine sslEngine = sslContext.newEngine(ctx.alloc(),
116-
inetAddress.getHostName(), inetAddress.getPort());
95+
final SSLEngine sslEngine;
96+
if (sslContext instanceof OpenSslContext) {
97+
// TODO(nmittler): Unsupported for OpenSSL in Netty < 4.1.Beta6.
98+
// Until we upgrade Netty, uncomment the line below when testing with OpenSSL.
99+
//sslEngine = sslContext.newEngine(ctx.alloc());
100+
sslEngine = sslContext.newEngine(ctx.alloc(),
101+
inetAddress.getHostName(), inetAddress.getPort());
102+
} else {
103+
sslEngine = sslContext.newEngine(ctx.alloc(),
104+
inetAddress.getHostName(), inetAddress.getPort());
105+
}
117106
SSLParameters sslParams = new SSLParameters();
118107
sslParams.setEndpointIdentificationAlgorithm("HTTPS");
119108
sslEngine.setSSLParameters(sslParams);

0 commit comments

Comments
 (0)