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

Handle multiple RST_STREAM frames #184

Merged

Conversation

jonathanjameswatson
Copy link
Contributor

When a client receives two RST_STREAM frames, a NYI exception is raised. This is not ideal, as servers are allowed to send multiple RST_STREAM frames.

From RFC7540§5.4.2:

A RST_STREAM is the last frame that an endpoint can send on a stream. The peer that sends the RST_STREAM frame MUST be prepared to receive any frames that were sent or enqueued for sending by the remote peer. These frames can be ignored, except where they modify connection state (such as the state maintained for header compression Section 4.3 or flow control).

Normally, an endpoint SHOULD NOT send more than one RST_STREAM frame for any stream. However, an endpoint MAY send additional RST_STREAM frames if it receives frames on a closed stream after more than a round-trip time. This behavior is permitted to deal with misbehaving implementations.

The first RST_STREAM frame should close the stream. In the closed state, extra RST_STREAM frames should be ignored (unless they arrive after a "significant" amount of time).

From RFC7540§5.1:

Endpoints MUST ignore WINDOW_UPDATE or RST_STREAM frames received in this state, though endpoints MAY choose to treat frames that arrive a significant time after sending END_STREAM as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.

Here is a relevant issue:

dotnet/aspnetcore#32442

I have added a test for this problem, and will add a case to solve it soon.

@anmonteiro
Copy link
Owner

Thanks for this, I’ll look over it soon. Note that we might need to do the same for the server implementation (up to you whether you add it in this PR or another one)

@jonathanjameswatson
Copy link
Contributor Author

Looking at the match statements in server_connection.ml's process_rst_stream_frame, I would expect the server to not run into this problem. I'll try to write a test to check.

@jonathanjameswatson
Copy link
Contributor Author

I have fixed the client and added a server test (that might need improvement), which passes.

@jonathanjameswatson jonathanjameswatson marked this pull request as ready for review August 23, 2022 16:03
@anmonteiro
Copy link
Owner

I added a new test verifying we also behave correctly for 2 RST_STREAM frames with a No_error payload.

I have fixed the client and added a server test (that might need improvement), which passes.

Looking over the code in server_connection, I feel like what might be happening is that we aren't ever calling the stream-level error handler. That's why your test passes.

A follow-up PR could unify the behavior with the client implementation, if it makes sense.

@jonathanjameswatson
Copy link
Contributor Author

Sounds good! That would also be useful for solving an issue I'll likely raise tomorrow where it seems that the server continues to send RESET_STREAM and DATA frames after sending a RESET_STREAM frame due to a malformed content-length header.

@jonathanjameswatson
Copy link
Contributor Author

jonathanjameswatson commented Aug 24, 2022

I added a new test verifying we also behave correctly for 2 RST_STREAM frames with a No_error payload.

Also, this makes me think that the error code might not be relevant, as far as the above parts of the protocol mention. Would it make sense to have the match statement in client_connection look like the following instead:

(match respd.state, error_code with
| Idle, _ -> ...
| Closed _, _ -> ()
| Active _, Error_code.NoError -> ...
| _ -> ...)

@anmonteiro
Copy link
Owner

I applied your suggestion, thanks!

@anmonteiro anmonteiro merged commit 6579ed3 into anmonteiro:master Aug 25, 2022
@jonathanjameswatson jonathanjameswatson deleted the handle-multiple-rst-streams branch September 8, 2022 11:11
anmonteiro added a commit to anmonteiro/opam-repository that referenced this pull request Mar 17, 2023
…2-async (0.10.0)

CHANGES:

- hpack: fix a case where hpack would raise an array out of bounds exception
  ([anmonteiro/ocaml-h2#183](anmonteiro/ocaml-h2#183))
  ([@jonathanjameswatson](https://github.com/jonathanjameswatson))
- h2: (client) handle multiple RST_STREAM frames
  ([anmonteiro/ocaml-h2#184](anmonteiro/ocaml-h2#184))
  ([@jonathanjameswatson](https://github.com/jonathanjameswatson))
- h2: (client) Fix a race condition with `~flush_headers_immediately:false` and
  empty request bodies
  ([anmonteiro/ocaml-h2#186](anmonteiro/ocaml-h2#186))
- h2: Make `H2.Reqd.error_code` part of the public interface
  ([anmonteiro/ocaml-h2#188](anmonteiro/ocaml-h2#188))
- h2: Add `~request_method` argument to `H2.Method.body_length`
  ([anmonteiro/ocaml-h2#190](anmonteiro/ocaml-h2#190))
  ([@jonathanjameswatson](https://github.com/jonathanjameswatson))
- h2: Don't send any frames on a stream after an `RST_STREAM` frame
  ([anmonteiro/ocaml-h2#187](anmonteiro/ocaml-h2#187),
  [anmonteiro/ocaml-h2#194](anmonteiro/ocaml-h2#194))
- h2: call error handler on the client if the remote peer closes the
  commmunication channel
  ([anmonteiro/ocaml-h2#177](anmonteiro/ocaml-h2#177),
  [anmonteiro/ocaml-h2#196](anmonteiro/ocaml-h2#194))
- h2: when reprioritizing a stream, respect its new priority (accounts for
  inferred default priority when a dependent stream is not in the tree
  ([RFC7540§5.3.1](https://www.rfc-editor.org/rfc/rfc7540.html#section-5.3.1)))
  ([anmonteiro/ocaml-h2#200](anmonteiro/ocaml-h2#200))
- h2: don't remove parent streams from the scheduler if they have children
  ([anmonteiro/ocaml-h2#201](anmonteiro/ocaml-h2#201))
- h2: don't schedule streams as dependencies of others marked for removal
  ([anmonteiro/ocaml-h2#205](anmonteiro/ocaml-h2#205))
- h2: revise scheduling algorithm to avoid starvation
  ([anmonteiro/ocaml-h2#199](anmonteiro/ocaml-h2#199),
  [anmonteiro/ocaml-h2#204](anmonteiro/ocaml-h2#204), reported in
  [anmonteiro/ocaml-h2#162](anmonteiro/ocaml-h2#162), thanks
  [@quernd](https://github.com/quernd))
- h2-eio: adapt to the next gluten-eio version
  ([anmonteiro/ocaml-h2#210](anmonteiro/ocaml-h2#210))
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