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

Drop frames after reset #106

Closed
wants to merge 1 commit into from

Conversation

edsko
Copy link
Collaborator

@edsko edsko commented Jan 20, 2024

I don't have a small reproducer for this, but I'm seeing that when I'm sending an ill-formed gRPC request to one of Google's servers (specifically, when I use a GET request instead of a POST request), I'm getting a response back from the server that looks something like this:

HyperText Transfer Protocol 2
    Stream: HEADERS, Stream ID: 1, Length 91, 200 OK
        (..)
        Header: :status: 200 OK
        Header: content-type: application/grpc
        Header: grpc-status: 2
        Header: grpc-message: Bad method header
HyperText Transfer Protocol 2
    Stream: RST_STREAM, Stream ID: 1, Length 4
        Length: 4
        Type: RST_STREAM (3)
        Flags: 0x00
        0... .... .... .... .... .... .... .... = Reserved: 0x0
        .000 0000 0000 0000 0000 0000 0000 0001 = Stream Identifier: 1
        Error: NO_ERROR (0)

and this then repeats a few times (within a single packet). I don't know why this repeats, but both the Google Python implementation and the the C++ implementation do this. When this happens, http2 (the lib) throws an undefined exception after it receives another HTTP2 messages on that now-reset stream. This commit changes this to simply drop such messages instead.

The spec (https://datatracker.ietf.org/doc/html/rfc7540#section-6.4) is strangely silent on this topic: it says that when you receive a RST_STREAM, you MUST NOT send any messages on that stream anymore, and when you send a RST_STREAM, you MUST be prepared to receive frames that your counterpart might have sent before it received the RST_STREAM. However, it is silent on whether or not it's legal to send further frames after sending a RST_STREAM, which is what we are observing here.

I don't have a small reproducer for this, but I'm seeing that when I'm sending
an ill-formed gRPC request to one of Google's servers (specifically, when I use
a `GET` request instead of a `POST` request), I'm getting a response back from
the server that looks something like this:

```
HyperText Transfer Protocol 2
    Stream: HEADERS, Stream ID: 1, Length 91, 200 OK
        (..)
        Header: :status: 200 OK
        Header: content-type: application/grpc
        Header: grpc-status: 2
        Header: grpc-message: Bad method header
HyperText Transfer Protocol 2
    Stream: RST_STREAM, Stream ID: 1, Length 4
        Length: 4
        Type: RST_STREAM (3)
        Flags: 0x00
        0... .... .... .... .... .... .... .... = Reserved: 0x0
        .000 0000 0000 0000 0000 0000 0000 0001 = Stream Identifier: 1
        Error: NO_ERROR (0)
```

_and this then repeats_ a few times (within a single packet). I don't know why
this repeats, but both the Google Python implementation and the the C++
implementation do this. When this happens, `http2` (the lib) throws an
`undefined` exception after it receives another HTTP2 messages on that
now-reset stream. This commit changes this to simply _drop_ such messages
instead.

The spec (https://datatracker.ietf.org/doc/html/rfc7540#section-6.4) is
strangely silent on this topic: it says that when you _receive_ a `RST_STREAM`,
you MUST NOT send any messages on that stream anymore, and when you _send_ a
`RST_STREAM`, you MUST be prepared to receive frames that your counterpart
might have sent before it received the `RST_STREAM`. However, it is silent on
whether or not it's legal to _send_ further frames after _sending_ a
`RST_STREAM`, which is what we are observing here.
@kazu-yamamoto kazu-yamamoto self-requested a review January 22, 2024 01:22
Copy link
Owner

@kazu-yamamoto kazu-yamamoto left a comment

Choose a reason for hiding this comment

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

I agree that the spec is ambiguous and support this change.

kazu-yamamoto added a commit that referenced this pull request Jan 22, 2024
@kazu-yamamoto
Copy link
Owner

Rebased, merged and released.
Thanks!

@kazu-yamamoto kazu-yamamoto deleted the branch kazu-yamamoto:master January 30, 2024 23:44
@edsko edsko deleted the edsko/frame-after-reset branch February 3, 2024 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants