Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.x Http2Connection should ignore a max concurrent streams setting of zero from the client #7346

Merged
merged 4 commits into from Aug 14, 2023

Conversation

thegridman
Copy link
Collaborator

@thegridman thegridman commented Aug 9, 2023

The Http2Connection updates some of its configuration based on that sent by the client. One of the config items updated is the "max concurrent streams" setting. The problem is that if the client sends zero for this setting then things can break. I discovered this when a number of our Coherence gRPC tests broke when I switched the server to use Nima and the client is still using grpc-java and Netty.

Client libraries such as grpc-java hard code this value to be zero and this breaks gRPC because the server cannot send messages down multiple streams. I have added an example of this where I have an existing bi-di channel request open and then send another request from the client that causes the server to send a message down the bi-di channel. This will break without the fix in this PR.

The fix I have done here is to ignore changing the "max concurrent streams" setting on the server if the client sends zero. then the grpc-java clients work. It might well be that I have mis-understood something about "max concurrent streams" and how the server should handle a value of zero. Trying to find out anything on the internet was all a bit vague.

I added a test nima/tests/integration/grpc/server/src/test/java/io/helidon/nima/tests/integration/grpc/webserver/EventsTest.java which works with my fix and fails without it.

@oracle-contributor-agreement oracle-contributor-agreement bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label Aug 9, 2023
@thegridman thegridman changed the title Http2Connection should ignore a max concurrent streams setting of zero from the client 4.x Http2Connection should ignore a max concurrent streams setting of zero from the client Aug 9, 2023
@thegridman thegridman added the 4.x Version 4.x label Aug 9, 2023
Copy link
Contributor

@danielkec danielkec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks more like a bug in the mentioned netty based client, citing the spec:

A value of 0 for SETTINGS_MAX_CONCURRENT_STREAMS SHOULD NOT be treated as special by endpoints. A zero value does prevent the creation of new streams; however, this can also happen for any limit that is exhausted with active streams. Servers SHOULD only set a zero value for short durations; if a server does not wish to accept requests, closing the connection is more appropriate.

Where A zero value does prevent the creation of new streams is important, we have to honor the 0 value like any other.

@tomas-langer
Copy link
Member

According to my understanding:

  • we should ignore this setting from the client, as we do not support server push, and that is the only case where we create concurrent streams
  • the value of maxClientConcurrentStreams can never be modified by the client, as this is the number of streams we allow the client to create, this is a big bug
  • if we fix this bug, the problem will disappear

tomas-langer
tomas-langer previously approved these changes Aug 11, 2023
Comment on lines -246 to -261
// Set server MAX_CONCURRENT_STREAMS limit when client sends number lower than hard limit
// from configuration. Refuse settings if client sends larger number than is configured.
this.clientSettings.presentValue(Http2Setting.MAX_CONCURRENT_STREAMS)
.ifPresent(it -> {
if (http2Config.maxConcurrentStreams() >= it) {
maxClientConcurrentStreams = it;
} else {
Http2GoAway frame =
new Http2GoAway(0,
Http2ErrorCode.PROTOCOL,
"Value of maximum concurrent streams limit " + it
+ " exceeded hard limit value "
+ http2Config.maxConcurrentStreams());
connectionWriter.write(frame.toFrameData(clientSettings, 0, Http2Flag.NoFlags.create()));
}
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

@danielkec danielkec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool thx for the fix!

@thegridman
Copy link
Collaborator Author

Although Daniel has approved this I do not have permissions to merge it so someone else will need to do it. Also, the build fails but I don't think it is related to this change as it is a different test failure every time I re-run the failing validate build.

@danielkec danielkec merged commit 5519bb0 into helidon-io:main Aug 14, 2023
12 checks passed
@thegridman thegridman deleted the http2-max-channels branch August 15, 2023 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.x Version 4.x OCA Verified All contributors have signed the Oracle Contributor Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants