Skip to content

Commit

Permalink
netty: migrate Server protocol negotiation to new style
Browse files Browse the repository at this point in the history
* Revert "Revert "netty: change server to new protocol negotiator model" (#5798)"

This reverts commit 4e5e19f.
  • Loading branch information
carl-mastrangelo committed Aug 14, 2019
1 parent ce53d0e commit 458f453
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 103 deletions.
2 changes: 2 additions & 0 deletions netty/src/main/java/io/grpc/netty/NettyServerHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,8 @@ public void handleProtocolNegotiationCompleted(
Attributes attrs, InternalChannelz.Security securityInfo) {
negotiationAttributes = attrs;
this.securityInfo = securityInfo;
super.handleProtocolNegotiationCompleted(attrs, securityInfo);
NettyClientHandler.writeBufferingAndRemove(ctx().channel());
}

InternalChannelz.Security getSecurityInfo() {
Expand Down
6 changes: 4 additions & 2 deletions netty/src/main/java/io/grpc/netty/NettyServerTransport.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,14 @@ public void operationComplete(ChannelFuture future) throws Exception {
}
}

ChannelHandler negotiationHandler = protocolNegotiator.newHandler(grpcHandler);
ChannelHandler bufferingHandler = new WriteBufferingAndExceptionHandler(negotiationHandler);

ChannelFutureListener terminationNotifier = new TerminationNotifier();
channelUnused.addListener(terminationNotifier);
channel.closeFuture().addListener(terminationNotifier);

ChannelHandler negotiationHandler = protocolNegotiator.newHandler(grpcHandler);
channel.pipeline().addLast(negotiationHandler);
channel.pipeline().addLast(bufferingHandler);
}

@Override
Expand Down
112 changes: 37 additions & 75 deletions netty/src/main/java/io/grpc/netty/ProtocolNegotiators.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import io.grpc.ChannelLogger;
import io.grpc.ChannelLogger.ChannelLogLevel;
import io.grpc.Grpc;
import io.grpc.InternalChannelz;
import io.grpc.InternalChannelz.Security;
import io.grpc.InternalChannelz.Tls;
import io.grpc.SecurityLevel;
Expand All @@ -38,11 +37,9 @@
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.HttpClientCodec;
Expand Down Expand Up @@ -111,34 +108,7 @@ public void log(ChannelLogLevel level, String messageFormat, Object... args) {}
* Create a server plaintext handler for gRPC.
*/
public static ProtocolNegotiator serverPlaintext() {
return new ProtocolNegotiator() {
@Override
public ChannelHandler newHandler(final GrpcHttp2ConnectionHandler handler) {
class PlaintextHandler extends ChannelHandlerAdapter {
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
// Set sttributes before replace to be sure we pass it before accepting any requests.
handler.handleProtocolNegotiationCompleted(Attributes.newBuilder()
.set(Grpc.TRANSPORT_ATTR_REMOTE_ADDR, ctx.channel().remoteAddress())
.set(Grpc.TRANSPORT_ATTR_LOCAL_ADDR, ctx.channel().localAddress())
.build(),
/*securityInfo=*/ null);
// Just replace this handler with the gRPC handler.
ctx.pipeline().replace(this, null, handler);
}
}

return new PlaintextHandler();
}

@Override
public void close() {}

@Override
public AsciiString scheme() {
return Utils.HTTP;
}
};
return new PlaintextProtocolNegotiator();
}

/**
Expand All @@ -149,7 +119,10 @@ public static ProtocolNegotiator serverTls(final SslContext sslContext) {
return new ProtocolNegotiator() {
@Override
public ChannelHandler newHandler(GrpcHttp2ConnectionHandler handler) {
return new ServerTlsHandler(sslContext, handler);
ChannelHandler gnh = new GrpcNegotiationHandler(handler);
ChannelHandler sth = new ServerTlsHandler(gnh, sslContext);
ChannelHandler wauh = new WaitUntilActiveHandler(sth);
return wauh;
}

@Override
Expand All @@ -163,67 +136,56 @@ public AsciiString scheme() {
};
}

@VisibleForTesting
static final class ServerTlsHandler extends ChannelInboundHandlerAdapter {
private final GrpcHttp2ConnectionHandler grpcHandler;
private final ChannelHandler next;
private final SslContext sslContext;

ServerTlsHandler(SslContext sslContext, GrpcHttp2ConnectionHandler grpcHandler) {
this.sslContext = sslContext;
this.grpcHandler = grpcHandler;
private ProtocolNegotiationEvent pne = ProtocolNegotiationEvent.DEFAULT;

ServerTlsHandler(ChannelHandler next, SslContext sslContext) {
this.sslContext = checkNotNull(sslContext, "sslContext");
this.next = checkNotNull(next, "next");
}

@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
super.handlerAdded(ctx);

SSLEngine sslEngine = sslContext.newEngine(ctx.alloc());
ctx.pipeline().addFirst(new SslHandler(sslEngine, false));
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
fail(ctx, cause);
ctx.pipeline().addBefore(ctx.name(), null, new SslHandler(sslEngine, false));
}

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof SslHandshakeCompletionEvent) {
if (evt instanceof ProtocolNegotiationEvent) {
pne = (ProtocolNegotiationEvent) evt;
} else if (evt instanceof SslHandshakeCompletionEvent) {
SslHandshakeCompletionEvent handshakeEvent = (SslHandshakeCompletionEvent) evt;
if (handshakeEvent.isSuccess()) {
if (NEXT_PROTOCOL_VERSIONS.contains(sslHandler(ctx.pipeline()).applicationProtocol())) {
SSLSession session = sslHandler(ctx.pipeline()).engine().getSession();
// Successfully negotiated the protocol.
// Notify about completion and pass down SSLSession in attributes.
grpcHandler.handleProtocolNegotiationCompleted(
Attributes.newBuilder()
.set(Grpc.TRANSPORT_ATTR_SSL_SESSION, session)
.set(Grpc.TRANSPORT_ATTR_REMOTE_ADDR, ctx.channel().remoteAddress())
.set(Grpc.TRANSPORT_ATTR_LOCAL_ADDR, ctx.channel().localAddress())
.build(),
new InternalChannelz.Security(new InternalChannelz.Tls(session)));
// Replace this handler with the GRPC handler.
ctx.pipeline().replace(this, null, grpcHandler);
} else {
fail(ctx,
unavailableException(
"Failed protocol negotiation: Unable to find compatible protocol"));
}
} else {
fail(ctx, handshakeEvent.cause());
if (!handshakeEvent.isSuccess()) {
logSslEngineDetails(Level.FINE, ctx, "TLS negotiation failed for new client.", null);
ctx.fireExceptionCaught(handshakeEvent.cause());
return;
}
SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
if (!NEXT_PROTOCOL_VERSIONS.contains(sslHandler.applicationProtocol())) {
logSslEngineDetails(Level.FINE, ctx, "TLS negotiation failed for new client.", null);
ctx.fireExceptionCaught(unavailableException(
"Failed protocol negotiation: Unable to find compatible protocol"));
return;
}
ctx.pipeline().replace(ctx.name(), null, next);
fireProtocolNegotiationEvent(ctx, sslHandler.engine().getSession());
} else {
super.userEventTriggered(ctx, evt);
}
super.userEventTriggered(ctx, evt);
}

private SslHandler sslHandler(ChannelPipeline pipeline) {
return pipeline.get(SslHandler.class);
}

@SuppressWarnings("FutureReturnValueIgnored")
private void fail(ChannelHandlerContext ctx, Throwable exception) {
logSslEngineDetails(Level.FINE, ctx, "TLS negotiation failed for new client.", exception);
ctx.close();
private void fireProtocolNegotiationEvent(ChannelHandlerContext ctx, SSLSession session) {
Security security = new Security(new Tls(session));
Attributes attrs = pne.getAttributes().toBuilder()
.set(GrpcAttributes.ATTR_SECURITY_LEVEL, SecurityLevel.PRIVACY_AND_INTEGRITY)
.set(Grpc.TRANSPORT_ATTR_SSL_SESSION, session)
.build();
ctx.fireUserEventTriggered(pne.withAttributes(attrs).withSecurity(security));
}
}

Expand Down

0 comments on commit 458f453

Please sign in to comment.