Skip to content

Commit

Permalink
H2 client should send ENABLE_PUSH=false setting for new connections (
Browse files Browse the repository at this point in the history
…#940)

Motivation:

To notify server-side that ST client currently does not support
server push, client should send `ENABLE_PUSH=false` setting when it
connects to the server.
If server sends a `PUSH_PROMISE` frame, client should send `GO_AWAY`
before closing the connection.

Modifications:

- Add `ENABLE_PUSH=false` and `MAX_CONCURRENT_STREAMS=0` to
the set of initial h2 settings;
- Send `GO_AWAY` frame with `PROTOCOL_ERROR` if client receives a
`PUSH_PROMISE` frame from server;

Result:

H2 client notifies server that it does not support server push and
sends `GO_AWAY` frame before closing the connection, if server sends
a push.
  • Loading branch information
idelpivnitskiy authored Feb 18, 2020
1 parent f93880e commit 9433208
Showing 1 changed file with 11 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2019 Apple Inc. and the ServiceTalk project authors
* Copyright © 2019-2020 Apple Inc. and the ServiceTalk project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,16 +21,19 @@
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http2.DefaultHttp2GoAwayFrame;
import io.netty.handler.codec.http2.Http2FrameCodecBuilder;
import io.netty.handler.codec.http2.Http2FrameLogger;
import io.netty.handler.codec.http2.Http2MultiplexHandler;

import java.util.function.BiPredicate;

import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
import static io.netty.handler.codec.http2.Http2FrameCodecBuilder.forClient;
import static io.netty.handler.logging.LogLevel.TRACE;

final class H2ClientParentChannelInitializer implements ChannelInitializer {

private final H2ProtocolConfig config;

H2ClientParentChannelInitializer(final H2ProtocolConfig config) {
Expand All @@ -47,6 +50,9 @@ public void init(final Channel channel) {
// the user to apply their own timeout at the call site.
.gracefulShutdownTimeoutMillis(-1);

// Notify server that this client does not support server push and request it to be disabled.
multiplexCodecBuilder.initialSettings().pushEnabled(false).maxConcurrentStreams(0L);

final BiPredicate<CharSequence, CharSequence> headersSensitivityDetector =
config.headersSensitivityDetector();
multiplexCodecBuilder.headerSensitivityDetector(headersSensitivityDetector::test);
Expand All @@ -64,6 +70,7 @@ public void init(final Channel channel) {

@ChannelHandler.Sharable
private static final class H2PushStreamHandler extends ChannelInboundHandlerAdapter {

static final ChannelInboundHandlerAdapter INSTANCE = new H2PushStreamHandler();

private H2PushStreamHandler() {
Expand All @@ -72,7 +79,9 @@ private H2PushStreamHandler() {

@Override
public void channelRegistered(final ChannelHandlerContext ctx) {
ctx.close(); // push streams are not supported
// See SETTINGS_ENABLE_PUSH in https://tools.ietf.org/html/rfc7540#section-6.5.2
ctx.writeAndFlush(new DefaultHttp2GoAwayFrame(PROTOCOL_ERROR));
// Http2ConnectionHandler.processGoAwayWriteResult will close the connection after GO_AWAY is flushed
}
}
}

0 comments on commit 9433208

Please sign in to comment.