Fixing erroneous server log when TLS nego fails

Only adding the server HTTP/2 handler after the TLS negotiation is successful.

Fixes #974
This commit is contained in:
nmittler 2015-09-09 07:13:12 -07:00
parent 31394aa9df
commit ccf328f367
2 changed files with 49 additions and 32 deletions

View File

@ -38,6 +38,7 @@ import io.grpc.internal.ServerTransportListener;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.handler.codec.http2.DefaultHttp2Connection;
import io.netty.handler.codec.http2.DefaultHttp2FrameReader;
import io.netty.handler.codec.http2.DefaultHttp2FrameWriter;
@ -84,19 +85,20 @@ class NettyServerTransport implements ServerTransport {
this.listener = listener;
// Create the Netty handler for the pipeline.
final NettyServerHandler handler = createHandler(listener);
final NettyServerHandler grpcHandler = createHandler(listener);
// Notify when the channel closes.
channel.closeFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
notifyTerminated(handler.connectionError());
notifyTerminated(grpcHandler.connectionError());
}
});
ChannelHandler handler = grpcHandler;
if (sslContext != null) {
SSLEngine sslEngine = sslContext.newEngine(channel.alloc());
channel.pipeline().addLast(ProtocolNegotiators.serverTls(sslEngine));
handler = ProtocolNegotiators.serverTls(sslEngine, grpcHandler);
}
channel.pipeline().addLast(handler);
}

View File

@ -76,7 +76,7 @@ public final class ProtocolNegotiators {
/**
* Create a TLS handler for HTTP/2 capable of using ALPN/NPN.
*/
public static ChannelHandler serverTls(SSLEngine sslEngine) {
public static ChannelHandler serverTls(SSLEngine sslEngine, final ChannelHandler grpcHandler) {
Preconditions.checkNotNull(sslEngine, "sslEngine");
final SslHandler sslHandler = new SslHandler(sslEngine, false);
@ -97,11 +97,11 @@ public final class ProtocolNegotiators {
if (evt instanceof SslHandshakeCompletionEvent) {
SslHandshakeCompletionEvent handshakeEvent = (SslHandshakeCompletionEvent) evt;
if (handshakeEvent.isSuccess()) {
if (applicationProtocol(ctx) != null) {
// Successfully negotiated the protocol.
ctx.pipeline().remove(this);
if (sslHandler(ctx).applicationProtocol() != null) {
// Successfully negotiated the protocol. Replace this handler with
// the GRPC handler.
ctx.pipeline().replace(this, null, grpcHandler);
} else {
fail(ctx, new Exception(
"Failed protocol negotiation: Unable to find compatible protocol."));
}
@ -113,34 +113,16 @@ public final class ProtocolNegotiators {
}
private void fail(ChannelHandlerContext ctx, Throwable exception) {
log.log(Level.FINE, errorMessage(ctx), exception);
Level level = Level.FINE;
if (log.isLoggable(level)) {
log.log(level, errorMessage(ctx), exception);
}
ctx.close();
}
private String errorMessage(ChannelHandlerContext ctx) {
StringBuilder builder = new StringBuilder("TLS negotiation failed for new client. ");
SSLEngine engine = sslHandler(ctx).engine();
if (engine instanceof OpenSslEngine) {
builder.append("OpenSSL version: ");
builder.append("0x").append(Integer.toHexString(OpenSsl.version()));
builder.append(" [").append(OpenSsl.versionString()).append(']');
builder.append(". ALPN supported: ").append(OpenSsl.isAlpnSupported()).append(". ");
} else if (JettyTlsUtil.isJettyAlpnConfigured()) {
builder.append("Jetty ALPN configured. ");
} else if (JettyTlsUtil.isJettyNpnConfigured()) {
builder.append("Jetty NPN configured. ");
}
builder.append("Enabled ciphers=");
builder.append(Arrays.toString(enabledCiphers(ctx))).append(". ");
return builder.toString();
}
private String applicationProtocol(ChannelHandlerContext ctx) {
return sslHandler(ctx).applicationProtocol();
}
private String[] enabledCiphers(ChannelHandlerContext ctx) {
return sslHandler(ctx).engine().getEnabledCipherSuites();
StringBuilder builder = new StringBuilder("TLS negotiation failed for new client.\n");
return sslEngineDetails(sslHandler(ctx), builder).toString();
}
private SslHandler sslHandler(ChannelHandlerContext ctx) {
@ -213,6 +195,39 @@ public final class ProtocolNegotiators {
return Status.UNAVAILABLE.withDescription(msg).asRuntimeException();
}
private static StringBuilder sslEngineDetails(SslHandler sslHandler, StringBuilder builder) {
SSLEngine engine = sslHandler.engine();
builder.append("SSLEngine Details: [\n");
if (engine instanceof OpenSslEngine) {
builder.append(" OpenSSL, ");
builder.append("Version: 0x").append(Integer.toHexString(OpenSsl.version()));
builder.append(" (").append(OpenSsl.versionString()).append("), ");
builder.append("ALPN supported: ").append(OpenSsl.isAlpnSupported());
} else if (JettyTlsUtil.isJettyAlpnConfigured()) {
builder.append(" Jetty ALPN");
} else if (JettyTlsUtil.isJettyNpnConfigured()) {
builder.append(" Jetty NPN");
}
builder.append("\n TLS Protocol: ");
builder.append(engine.getSession().getProtocol());
builder.append("\n Application Protocol: ");
builder.append(sslHandler.applicationProtocol());
builder.append("\n Need Client Auth: " );
builder.append(engine.getNeedClientAuth());
builder.append("\n Want Client Auth: ");
builder.append(engine.getWantClientAuth());
builder.append("\n Supported protocols=");
builder.append(Arrays.toString(engine.getSupportedProtocols()));
builder.append("\n Enabled protocols=");
builder.append(Arrays.toString(engine.getEnabledProtocols()));
builder.append("\n Supported ciphers=");
builder.append(Arrays.toString(engine.getSupportedCipherSuites()));
builder.append("\n Enabled ciphers=");
builder.append(Arrays.toString(engine.getEnabledCipherSuites()));
builder.append("\n]");
return builder;
}
/**
* Buffers all writes until either {@link #writeBufferedAndRemove(ChannelHandlerContext)} or
* {@link #fail(ChannelHandlerContext, Throwable)} is called. This handler allows us to