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

Better handle DATA frames with end stream set #1139

Merged
merged 1 commit into from
Feb 17, 2021

Conversation

glbrntt
Copy link
Collaborator

@glbrntt glbrntt commented Feb 16, 2021

Motivation:

If a peer doesn't follow spec and sends the client a DATA frame with end
stream set, the client will ignore the fact that end stream was set.
When the stream channel closes just after, the call is unaware of why it
was closed (because it hasn't received a final status) which leads to a
pretty non-descript error message.

Modifications:

Add a 'receiveEndOfResponseStream' to the client state machine which
produces a 'GRPCStatus' if the end stream is unexpected and should not
be ignored.

Result:

Calls will terminate with an 'internal error' status and a message about
a protocol violation if the server sends a data frame with end stream
set.

Resolves #1136

@glbrntt glbrntt added the 🔨 semver/patch No public API change. label Feb 16, 2021
@glbrntt glbrntt requested a review from Lukasa February 16, 2021 16:00
/// set. However, we will tolerate end stream on a DATA frame providing we have received trailers
/// containing 'grpc-status' (i.e. we are in the 'clientClosedServerClosed' state). In cases where
/// we don't expect end of stream on a DATA frame we will emit a status with a message explaining
/// the protocol violation.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm a bit confused about this state description. When will we receive a DATA frame after having received a HEADERS frame that contains trailers? NIOHTTP2 enforces that the trailers header block must have END_STREAM, so no DATA frame on that stream may validly follow it. What have I missed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah, right, that's a good point. That was me assuming a state in which it could be valid. Really the case we tolerate it is "the rpc is already complete".

Motivation:

If a peer doesn't follow spec and sends the client a DATA frame with end
stream set, the client will ignore the fact that end stream was set.
When the stream channel closes just after, the call is unaware of why it
was closed (because it hasn't received a final status) which leads to a
pretty non-descript error message.

Modifications:

Add a 'receiveEndOfResponseStream' to the client state machine which
produces a 'GRPCStatus' if the end stream is unexpected and should not
be ignored.

Result:

Calls will terminate with an 'internal error' status and a message about
a protocol violation if the server sends a data frame with end stream
set.

Resolves grpc#1136
@glbrntt glbrntt force-pushed the gb-handle-end-stream-data branch from dbedaed to be64c62 Compare February 17, 2021 09:32
@Lukasa Lukasa merged commit 28d7266 into grpc:main Feb 17, 2021
@glbrntt glbrntt deleted the gb-handle-end-stream-data branch June 8, 2021 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔨 semver/patch No public API change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Client doesn't handle DATA frames with end stream set gracefully
2 participants