Commit Graph

98 Commits

Author SHA1 Message Date
David Barsky
d3b9f1e36a feat(lib): switch from log to tracing (#475) 2020-07-07 15:55:24 -07:00
Sean McArthur
d6dc63276f Fix receiving a GOAWAY frame from updating the max recv ID
Receiving a GOAWAY should update the max *send* ID, it shouldn't affect
the max recv.
2020-03-25 10:08:13 -07:00
Sean McArthur
ec751f3696 Remove Unpin requirement for the send Buf 2019-12-06 11:40:08 -08:00
Sean McArthur
4398e169e8 Update to Tokio 0.2 (#428) 2019-11-27 14:53:57 -08:00
Sean McArthur
86e53054a6 Change ReserveCapacity to expanded FlowControl type (#423)
- Adds `FlowControl::available_capacity` method.
- Adds `FlowControl::used_capacity` method.
2019-10-08 11:28:15 -07:00
Sean McArthur
4c1d797712 Add ability to adjust INITIAL_WINDOW_SIZE setting on an existing connection (#421) 2019-10-07 15:29:23 -07:00
Michael Beaumont
fac165e451 Add server support for push (#327)
Closes #291, closes #185
2019-09-16 11:30:58 -07:00
Sean McArthur
2d90efee17 Prune futures-* dependencies 2019-08-30 14:53:49 -07:00
Sean McArthur
f31ec5d0da Remove deprecated-in-0.1.x APIs 2019-08-20 15:15:04 -07:00
Gurwinder Singh
c8fefd49f1 Update lib to std-future 2019-08-16 18:47:47 -07:00
Jakub Beránek
db6b841e67 Update crate to Rust 2018 (#383) 2019-07-23 10:18:43 -07:00
Sean McArthur
ab52cf9b30 Send RST_STREAM of STREAM_CLOSED instead of GOAWAY if stream may have been forgotten 2019-06-28 12:48:42 -07:00
Sean McArthur
f8f05d04e7 Fix trailers without EOS flag to be a stream instead of connection error (#377)
[Trailers without EOS](https://httpwg.org/specs/rfc7540.html#HttpSequence):

> An endpoint that receives a HEADERS frame without the END_STREAM flag set after receiving a final (non-informational) status code MUST treat the corresponding request or response as malformed (Section 8.1.2.6).

[Malformed messages](https://httpwg.org/specs/rfc7540.html#malformed):

> Malformed requests or responses that are detected MUST be treated as a stream error (Section 5.4.2) of type PROTOCOL_ERROR.
2019-06-26 13:38:06 -07:00
Eliza Weisman
0e9fbe4a90 Log protocol error causes at debug (#371)
Currently, there are many cases where `h2` will fail a connection or
stream with a PROTOCOL_ERROR, without recording why the protocol error
occurred. Since protocol errors may result from a bug in `h2` or from a
misbehaving peer, it is important to be able to debug the cause of
protocol errors.

This branch adds a log line to almost all cases where a protocol error
occurs. I've tried to make the new log lines consistent with the
existing logging, and in some cases, changed existing log lines to make
them internally consistent with other log lines in that module. All
receive-side errors that would send a reset are now logged at the debug
level, using a formatting based on the format used in `framed_read`.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
2019-06-17 14:14:40 -07:00
Alex Touchet
e13645c091 Update repo URLs (#370) 2019-06-04 23:06:13 -07:00
Sean McArthur
611e1ca010 Clear recv buffer when stream refs are dropped 2019-06-04 19:09:30 -07:00
Sean McArthur
91819bf25e check for overly large header field in send_headers 2019-05-29 17:19:55 -07:00
Sean McArthur
492f4e7f11 Make 'pending reset' streams not count towards active streams 2019-03-12 17:17:02 -07:00
Sean McArthur
feff97905f Notify RecvStream tasks if SendStream sends a local reset 2019-03-12 17:17:02 -07:00
Eliza Weisman
d6e1fbeed8 Fix race in stream ref count (#338)
Fixes #326
2019-01-11 22:41:35 -08:00
Sean McArthur
c7d4182ffe Release closed streams capacity back to connection (#334)
Previously, any streams that were dropped or closed while not having
consumed the inflight received window capacity would simply leak that
capacity for the connection. This could easily happen if a `RecvStream`
were dropped before fully consuming the data, and therefore a user would
have no idea how much capacity to release in the first place. This
resulted in stalled connections that would never have capacity again.
2018-12-05 09:44:20 -08:00
Carl Lerche
8387355e1b Avoid locking when printing (#333)
* Avoid locking when printing

It is not obvious that attempting to print the
value of a struct could cause a deadlock. To avoid
this, this patch does not lock the mutex when generating
a debug representation of the h2 struct.

* Use try_lock
2018-11-29 21:50:53 -08:00
Michael Beaumont
fc5efe73d6 Add OpaqueStreamRef constructor (#325)
Closes #318
2018-10-17 23:09:28 -07:00
Michael Beaumont
6b23542a55 Add client support for server push (#314)
This patch exposes push promises to the client API.

Closes #252
2018-10-16 12:51:08 -07:00
Geoffry Song
6d8554a23c Reassign capacity from reset streams. (#320)
I believe this was an oversight - a stream that is reset can still have some
capacity assigned to it (e.g. if said capacity was assigned in the same poll as
the reset), which should be redistributed.
2018-10-16 12:14:42 -07:00
Robert Ying
b116605560 Check whether the send side is not idle, not the recv side (#313)
* Check whether the send side is not idle, not the recv side
* Ensure sure we're handling window updates for the right side
* Add failing test
2018-10-16 12:03:56 -07:00
Eliza Weisman
f3806d5144 Add stream_id accessors to public API types (#292)
Problem:

Applications may want to access the underlying h2 stream ID for
diagnostics, etc. Stream IDs were not previously exposed in public APIs.

Solution:

Added a new public `share::StreamId` type, which has a more restricted 
API than the internal `frame::StreamId` type. The public API types 
`SendStream`, `RecvStream`, `ReleaseCapacity`, 
`client::ResponseFuture`, and `server::SendResponse` now all have 
`stream_id` methods which return the stream ID of the corresponding 
stream.

Closes #289.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
2018-07-12 21:01:57 -07:00
Geoffry Song
23234fa14f Promote SendRequest::pending to an OpaqueStreamRef. (#281)
Because `self.pending` doesn't necessarily get cleaned up in a timely fashion -
rather, only when the user calls `poll_ready()` - it was possible for it to
refer to a stream that has already been closed. This would lead to a panic the
next time that `poll_ready()` was called.

Instead, use an `OpaqueStreamRef`, bumping the refcount.

A change to an existing test is included which demonstrates the issue.
2018-06-06 10:16:22 -07:00
Sean McArthur
3a4633d205 add SendResponse::poll_reset and SendStream::poll_reset to listen for reset streams (#279) 2018-05-30 22:57:43 +02:00
Carl Lerche
bb454e017c Enforce monotonic stream IDs for push promises (#275)
Previously, monotonic stream IDs (spec 5.1.1) for push promises were not
enforced. This was due to push promises going through an entirely
separate code path than normally initiated streams.

This patch unifies the code path for initializing streams via both
HEADERS and PUSH_PROMISE. This is done by first calling `recv.open` in
both cases.

Closes #272
2018-05-14 10:20:57 -07:00
Carl Lerche
cf62b783e0 Misc bug fixes related to stream state (#273)
This patch includes two new significant debug assertions:

* Assert stream counts are zero when the connection finalizes.
* Assert all stream state has been released when the connection is 
  dropped.

These two assertions were added in an effort to test the fix provided
by #261. In doing so, many related bugs have been discovered and fixed.
The details related to these bugs can be found in #273.
2018-05-09 15:03:21 -07:00
Sean McArthur
fadec67fdf prevent a leak of 'active streams' if client request has user error (#266) 2018-04-26 18:20:32 -07:00
Geoffry Song
11f914150e Add some missing bounds checks. (#260) 2018-04-23 14:38:42 -07:00
Sean McArthur
1c5d4ded50 Add Graceful Shutdown support
If graceful shutdown is initiated, a GOAWAY of the max stream ID - 1 is
sent, followed by a PING frame, to measure RTT. When the PING is ACKed,
the connection sends a new GOAWAY with the proper last processed stream
ID. From there, once all active streams have completely, the connection
will finally close.
2018-03-29 13:51:30 -07:00
Darren Tsung
f8baeb7211 Streams receiving peer reset clear pending send (#238)
Because streams that were being peer reset were not clearing pending
send frames / buffered_send_data, they were not being counted towards
the concurrency limit.
2018-03-13 12:47:57 -07:00
Darren Tsung
0c59957d88 When Streams are dropped, close Connection (#221) (#222)
When all Streams are dropped / finished, the Connection was held
open until the peer hangs up. Instead, the Connection should hang up
once it knows that nothing more will be sent.

To fix this, we notify the Connection when a stream is no longer
referenced. On the Connection poll(), we check that there are no
active, held, reset streams or any references to the Streams
and transition to sending a GOAWAY if that is case.

The specific behavior depends on if running as a client or server.
2018-02-15 13:14:18 -08:00
Sean McArthur
aa23a9735d SETTINGS_MAX_HEADER_LIST_SIZE (#206)
This, uh, grew into something far bigger than expected, but it turns out, all of it was needed to eventually support this correctly.

- Adds configuration to client and server to set [SETTINGS_MAX_HEADER_LIST_SIZE](http://httpwg.org/specs/rfc7540.html#SETTINGS_MAX_HEADER_LIST_SIZE)
- If not set, a "sane default" of 16 MB is used (taken from golang's http2)
- Decoding header blocks now happens as they are received, instead of buffering up possibly forever until the last continuation frame is parsed.
- As each field is decoded, it's undecoded size is added to the total. Whenever a header block goes over the maximum size, the `frame` will be marked as such.
- Whenever a header block is deemed over max limit, decoding will still continue, but new fields will not be appended to `HeaderMap`. This is also can save wasted hashing.
- To protect against enormous string literals, such that they span multiple continuation frames, a check is made that the combined encoded bytes is less than the max allowed size. While technically not exactly what the spec suggests (counting decoded size instead), this should hopefully only happen when someone is indeed malicious. If found, a `GOAWAY` of `COMPRESSION_ERROR` is sent, and the connection shut down.
- After an oversize header block frame is finished decoding, the streams state machine will notice it is oversize, and handle that.
  - If the local peer is a server, a 431 response is sent, as suggested by the spec.
  - A `REFUSED_STREAM` reset is sent, since we cannot actually give the stream to the user.
- In order to be able to send both the 431 headers frame, and a reset frame afterwards, the scheduled `Canceled` machinery was made more general to a `Scheduled(Reason)` state instead.

Closes #18 
Closes #191
2018-01-05 09:23:48 -08:00
Sean McArthur
a89401dd91 reset pending push promises if user drops all refs (#199) 2017-12-20 16:50:20 -08:00
Sean McArthur
1552d62e7c ignore trailers for some time on locally reset streams (#194) 2017-12-19 15:06:05 -08:00
Sean McArthur
eafd6bfd98 release connection capacity when recv_data has stream error (#186) 2017-12-18 15:08:21 -08:00
Sean McArthur
1ea9a8fc7e ignore received frames on a stream locally reset for some time (#174)
- Adds config duration for how long to ignore frames on a reset stream
- Adds config for how many reset streams can be held at a time
2017-12-18 11:09:38 -08:00
Carl Lerche
9378846da8 Client should validate request URI. (#181)
This patch adds checks for the request URI and rejects invalid URIs. In
the case of forwarding an HTTP 1.1 request with a path, an "http" pseudo
header is added to satisfy the HTTP/2.0 spec.

Closes #179
2017-12-11 13:42:00 -06:00
Sean McArthur
6c68f72fbd notify stream send task when receiving EOF (#178)
* notify stream send task when receiving EOF

* record a conn_error on eof so client can see it

* fix stream id overflow test
2017-12-01 15:58:04 -08:00
Sean McArthur
2be2523162 notify stream refs when the connection receives EOF (#176) 2017-11-28 13:42:22 -08:00
Carl Lerche
c23d11306e Add RecvStream::is_end_stream. (#165)
This function returns true if the `RecvStream` has reached an end of
stream state. This is intended to replace `is_empty` which has confusing
behavior.
2017-10-21 09:59:27 -07:00
Carl Lerche
c4fc2928fe API cleanup (#155)
* Change send_reset to take &mut self.

While calling this function is the last thing that should be done with
the instance, the intent of the h2 library is not to be used directly by
users, but to be used as an implementation detail by other libraries.

Requiring `self` on `send_reset` is pretty annoying when calling the
function from inside a `Future` implementation. Also, all the other fns
on the type take `&mut self`.

* Remove the P: Peer generic from internals

* Split out `Respond` from `server::Stream`

This new type is used to send HTTP responses to the client as well as
reserve streams for push promises.

* Remove unused `Send` helper.

This could be brought back later when the API becomes stable.

* Unite `client` and `server` types

* Remove `B` generic from internal proto structs

This is a first step in removing the `B` generic from public API types
that do not strictly require it.

Currently, all public API types must be generic over `B` even if they do
not actually interact with the send data frame type. The first step in
removing this is to remove `B` as a generic on all internal types.

* Remove `Buffer<B>` from inner stream state

This is the next step in removing the `B` generic from all public API
types. The send buffer is the only type that requires `B`. It has now
been extracted from the rest of the stream state.

The strategy used in this PR requires an additional `Arc` and `Mutex`,
but this is not a fundamental requirement. The additional overhead can
be avoided with a little bit of unsafe code. However, this optimization
should not be made until it is proven that it is required.

* Remove `B` generic from `Body` + `ReleaseCapacity`

This commit actually removes the generic from these two public API
types. Also note, that removing the generic requires that `B: 'static`.
This is because there is no more generic on `Body` and `ReleaseCapacity`
and the compiler must be able to ensure that `B` outlives all `Body` and
`ReleaseCapacity` handles.

In practice, in an async world, passing a non 'static `B` is never going
to happen.

* Remove generic from `ResponseFuture`

This change also makes generic free types `Send`. The original strategy
of using a trait object meant that those handles could not be `Send`.
The solution was to avoid using the send buffer when canceling a stream.
This is done by transitioning the stream state to `Canceled`, a new
`Cause` variant.

* Simplify Send::send_reset

Now that implicit cancelation goes through a separate path, the
send_reset function can be simplified.

* Export types common to client & server at root

* Rename Stream -> SendStream, Body -> RecvStream

* Implement send_reset on server::Respond
2017-10-19 20:02:08 -07:00
Sean McArthur
5c1bde7d62 add set_target_window_size methods to Server and Client (#149)
Closes #101
2017-10-13 11:19:56 -07:00
Holt Chesley
2aee78c7d7 Issue 128: Convert frame::Reason to struct (#142)
Alter frame::Reason to a struct with a single u32 member.
Introduce Constants to the impl for existing Reasons. Change all usage
in the library and its tests to adopt this change,
using the new constants.
2017-10-08 13:13:07 -07:00
Sean McArthur
bc679035f9 remove panic from Debug of StreamRef is mutex is poisoned 2017-10-06 14:20:32 -07:00
Eliza Weisman
2e3dcf602c StreamRef sends RST_STREAM on drop (#109)
This PR modifies the `Drop` implementation for `StreamRef` to reset the underlying stream if it is the last reference to that stream. Since both `Stream` and `Body` are internally just a `StreamRef`, this means they will both reset the stream on drop; thus, this closes #100.

The assertion that the store no longer contains the dropped stream ID at the end of the `Drop` method  had to be removed, as the stream has to be reset from inside of a `transition` block (which now manages releasing that ID for us), and the `transition` closure moves the value of `stream`, making the assertion no longer possible.

Modifications to some of the tests in `flow_control.rs` were also necessary, in order to prevent `StreamRef`s from being dropped too early.
2017-10-05 18:05:18 -05:00