Skip to content

Commit 8e21a74

Browse files
0x676e67seanmonstardswijNoah-Kennedyniceskylei
authored
Merge patch (hyperium#16)
* v0.3.26 * Rename project to `rh2` * Refactor frame sending custom implementation * Export frame `PseudoOrder` settings * Reduce unnecessary Option packaging * v0.3.27 * fix(frame/headers): Fix error when headers priority is empty * v0.3.29 * feat(frame/headers): Packaging headers pseudo order type (hyperium#8) * feat(frame/settings): Packaging settings type (hyperium#9) * Initialize frame settings order in advance * v0.3.31 * feat(frame): Add unknown_setting frame settings (hyperium#10) * Add unknown_setting patch * Customize all Http Settings order * v0.3.40 * fix(frame): Fix unknown setting encode (hyperium#11) * v0.3.41 * feat: Replace with static settings (hyperium#12) * v0.3.50 * feat: Destructive update, fixed-length array records the setting frame order (hyperium#13) * v0.3.60 * Update README.md * Sync upstream (hyperium#14) * fix: streams awaiting capacity lockout (hyperium#730) (hyperium#734) This PR changes the the assign-capacity queue to prioritize streams that are send-ready. This is necessary to prevent a lockout when streams aren't able to proceed while waiting for connection capacity, but there is none. Closes hyperium/hyper#3338 Co-authored-by: dswij <[email protected]> * v0.3.23 * streams: limit error resets for misbehaving connections This change causes GOAWAYs to be issued to misbehaving connections which for one reason or another cause us to emit lots of error resets. Error resets are not generally expected from valid implementations anyways. The threshold after which we issue GOAWAYs is tunable, and will default to 1024. * Prepare v0.3.24 * perf: optimize header list size calculations (hyperium#750) This speeds up loading blocks in cases where we have many headers already. * v0.3.25 * refactor: cleanup new unused warnings (hyperium#757) * fix: limit number of CONTINUATION frames allowed Calculate the amount of allowed CONTINUATION frames based on other settings. max_header_list_size / max_frame_size That is about how many CONTINUATION frames would be needed to send headers up to the max allowed size. We then multiply by that by a small amount, to allow for implementations that don't perfectly pack into the minimum frames *needed*. In practice, *much* more than that would be a very inefficient peer, or a peer trying to waste resources. See https://seanmonstar.com/blog/hyper-http2-continuation-flood/ for more info. * v0.3.26 * fix: return a WriteZero error if frames cannot be written (hyperium#783) Some operating systems will allow you continually call `write()` on a closed socket, and will return `Ok(0)` instead of an error. This patch checks for a zero write, and instead of looping forever trying to write, returns a proper error. Closes hyperium#781 Co-authored-by: leibeiyi <[email protected]> * lints: fix unexpected cfgs warnings * ci: pin deps for MSRV * ci: pin more deps for MSRV job (hyperium#817) * fix: notify_recv after send_reset() in reset_on_recv_stream_err() to ensure local stream is released properly (hyperium#816) Similar to what have been done in fn send_reset<B>(), we should notify RecvStream that is parked after send_reset(). Co-authored-by: Jiahao Liang <[email protected]> --------- Co-authored-by: Sean McArthur <[email protected]> Co-authored-by: dswij <[email protected]> Co-authored-by: Noah Kennedy <[email protected]> Co-authored-by: beiyi lei <[email protected]> Co-authored-by: leibeiyi <[email protected]> Co-authored-by: Jiahao Liang <[email protected]> * v0.3.61 --------- Co-authored-by: Sean McArthur <[email protected]> Co-authored-by: dswij <[email protected]> Co-authored-by: Noah Kennedy <[email protected]> Co-authored-by: beiyi lei <[email protected]> Co-authored-by: leibeiyi <[email protected]> Co-authored-by: Jiahao Liang <[email protected]>
1 parent a3b3d71 commit 8e21a74

12 files changed

+215
-110
lines changed

CHANGELOG.md

+2-18
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,9 @@
1414

1515
* Limit number of CONTINUATION frames for misbehaving connections.
1616

17-
# 0.4.3 (March 15, 2024)
17+
# 0.3.25 (March 15, 2024)
1818

19-
* Fix flow control limits to not apply until receiving SETTINGS ack.
20-
* Fix not returning an error if IO ended without `close_notify`.
21-
* Improve performance of decoding many headers.
22-
23-
# 0.4.2 (January 17th, 2024)
24-
25-
* Limit error resets for misbehaving connections.
26-
* Fix selecting MAX_CONCURRENT_STREAMS value if no value is advertised initially.
27-
28-
# 0.4.1 (January 8, 2024)
29-
30-
* Fix assigning connection capacity which could starve streams in some instances.
31-
32-
# 0.4.0 (November 15, 2023)
33-
34-
* Update to `http` 1.0.
35-
* Remove deprecated `Server::poll_close()`.
19+
* Improve performance decoding many headers.
3620

3721
# 0.3.24 (January 17, 2024)
3822

README.md

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
# H2
22

3-
This project is forked from [h2](https://github.com/hyperium/h2)
4-
53
A Tokio aware, HTTP/2 client & server implementation for Rust.
64

75
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
8-
[![Crates.io](https://img.shields.io/crates/v/h2.svg)](https://crates.io/crates/h2)
9-
[![Documentation](https://docs.rs/h2/badge.svg)][dox]
6+
[![Crates.io](https://img.shields.io/crates/v/rh2.svg)](https://crates.io/crates/rh2)
7+
[![Documentation](https://docs.rs/rh2/badge.svg)][dox]
108

119
More information about this crate can be found in the [crate documentation][dox].
1210

13-
[dox]: https://docs.rs/h2
11+
[dox]: https://docs.rs/rh2
1412

1513
## Features
1614

@@ -34,19 +32,19 @@ This crate is now used by [hyper](https://github.com/hyperium/hyper), which will
3432

3533
## Usage
3634

37-
To use `h2`, first add this to your `Cargo.toml`:
35+
To use `rh2`, first add this to your `Cargo.toml`:
3836

3937
```toml
4038
[dependencies]
41-
h2 = "0.4"
39+
rh2 = "0.4"
4240
```
4341

4442
Next, add this to your crate:
4543

4644
```rust
47-
extern crate h2;
45+
extern crate rh2;
4846

49-
use h2::server::Connection;
47+
use rh2::server::Connection;
5048

5149
fn main() {
5250
// ...
@@ -71,3 +69,7 @@ actively maintained.
7169
[solicit]: https://github.com/mlalic/solicit
7270
[rust-http2]: https://github.com/stepancheg/rust-http2
7371
[h2spec]: https://github.com/summerwind/h2spec
72+
73+
## Accolades
74+
75+
The project is based on a fork of [h2](https://github.com/hyperium/h2).

src/client.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@
138138
use crate::codec::{Codec, SendError, UserError};
139139
use crate::ext::Protocol;
140140
use crate::frame::{
141-
Headers, Pseudo, PseudoOrder, Reason, Settings, SettingsOrder, StreamDependency, StreamId,
141+
Headers, Pseudo, PseudoOrder, PseudoOrders, Reason, Settings, SettingsOrder, StreamDependency,
142+
StreamId
142143
};
143144
use crate::proto::{self, Error};
144145
use crate::{FlowControl, PingPong, RecvStream, SendStream};
@@ -347,7 +348,7 @@ pub struct Builder {
347348
local_max_error_reset_streams: Option<usize>,
348349

349350
/// The headers frame pseudo order
350-
headers_pseudo_order: Option<[PseudoOrder; 4]>,
351+
headers_pseudo_order: Option<PseudoOrders>,
351352

352353
/// The headers frame priority
353354
headers_priority: Option<StreamDependency>,
@@ -677,20 +678,20 @@ impl Builder {
677678
}
678679

679680
/// Set http2 header pseudo order
680-
pub fn headers_psuedo(&mut self, headers_psuedo: Option<[PseudoOrder; 4]>) -> &mut Self {
681-
self.headers_pseudo_order = headers_psuedo;
681+
pub fn headers_psuedo(&mut self, order: [PseudoOrder; 4]) -> &mut Self {
682+
self.headers_pseudo_order = Some(order.into());
682683
self
683684
}
684685

685686
/// Set http2 header priority
686-
pub fn headers_priority(&mut self, headers_priority: Option<StreamDependency>) -> &mut Self {
687-
self.headers_priority = headers_priority;
687+
pub fn headers_priority(&mut self, headers_priority: StreamDependency) -> &mut Self {
688+
self.headers_priority = Some(headers_priority);
688689
self
689690
}
690691

691692
/// Settings frame order
692-
pub fn settings_order(&mut self, order: Option<[SettingsOrder; 2]>) -> &mut Self {
693-
self.settings.set_settings_order(order);
693+
pub fn settings_order(&mut self, order: [SettingsOrder; 8]) -> &mut Self {
694+
self.settings.set_settings_order(Some(order));
694695
self
695696
}
696697

@@ -1173,6 +1174,18 @@ impl Builder {
11731174
self
11741175
}
11751176

1177+
/// unknown_setting8
1178+
pub fn unknown_setting8(&mut self, enabled: bool) -> &mut Self {
1179+
self.settings.set_unknown_setting_8(enabled);
1180+
self
1181+
}
1182+
1183+
/// unknown_setting8
1184+
pub fn unknown_setting9(&mut self, enabled: bool) -> &mut Self {
1185+
self.settings.set_unknown_setting_9(enabled);
1186+
self
1187+
}
1188+
11761189
/// Sets the first stream ID to something other than 1.
11771190
#[cfg(feature = "unstable")]
11781191
pub fn initial_stream_id(&mut self, stream_id: u32) -> &mut Self {
@@ -1614,7 +1627,7 @@ impl Peer {
16141627
request: Request<()>,
16151628
protocol: Option<Protocol>,
16161629
end_of_stream: bool,
1617-
pseudo_order: Option<[PseudoOrder; 4]>,
1630+
pseudo_order: Option<PseudoOrders>,
16181631
headers_priority: Option<StreamDependency>,
16191632
) -> Result<Headers, SendError> {
16201633
use http::request::Parts;

src/codec/framed_write.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ where
133133

134134
loop {
135135
while !self.encoder.is_empty() {
136-
match self.encoder.next {
136+
let n = match self.encoder.next {
137137
Some(Next::Data(ref mut frame)) => {
138138
tracing::trace!(queued_data_frame = true);
139139
let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut());
@@ -148,6 +148,12 @@ where
148148
))?
149149
}
150150
};
151+
if n == 0 {
152+
return Poll::Ready(Err(io::Error::new(
153+
io::ErrorKind::WriteZero,
154+
"failed to write frame to socket",
155+
)));
156+
}
151157
}
152158

153159
match self.encoder.unset_frame() {

src/frame/headers.rs

+53-26
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub struct Pseudo {
7474
pub status: Option<StatusCode>,
7575

7676
// order of pseudo headers
77-
pub order: Option<[PseudoOrder; 4]>,
77+
pub order: PseudoOrders,
7878
}
7979

8080
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -85,6 +85,26 @@ pub enum PseudoOrder {
8585
Path,
8686
}
8787

88+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89+
pub struct PseudoOrders([PseudoOrder; 4]);
90+
91+
impl From<[PseudoOrder; 4]> for PseudoOrders {
92+
fn from(src: [PseudoOrder; 4]) -> Self {
93+
PseudoOrders(src)
94+
}
95+
}
96+
97+
impl Default for PseudoOrders {
98+
fn default() -> Self {
99+
PseudoOrders([
100+
PseudoOrder::Method,
101+
PseudoOrder::Scheme,
102+
PseudoOrder::Authority,
103+
PseudoOrder::Path,
104+
])
105+
}
106+
}
107+
88108
#[derive(Debug)]
89109
pub struct Iter {
90110
/// Pseudo headers
@@ -131,6 +151,13 @@ impl Headers {
131151
fields: HeaderMap,
132152
stream_dep: Option<StreamDependency>,
133153
) -> Self {
154+
// If the stream dependency is set, the PRIORITY flag must be set
155+
let flags = if stream_dep.is_some() {
156+
HeadersFlag(END_HEADERS | PRIORITY)
157+
} else {
158+
HeadersFlag::default()
159+
};
160+
134161
Headers {
135162
stream_id,
136163
stream_dep,
@@ -140,7 +167,7 @@ impl Headers {
140167
is_over_size: false,
141168
pseudo,
142169
},
143-
flags: HeadersFlag::default(),
170+
flags,
144171
}
145172
}
146173

@@ -580,7 +607,7 @@ impl Pseudo {
580607
method: Method,
581608
uri: Uri,
582609
protocol: Option<Protocol>,
583-
pseudo_order: Option<[PseudoOrder; 4]>,
610+
order: Option<PseudoOrders>,
584611
) -> Self {
585612
let parts = uri::Parts::from(uri);
586613

@@ -610,7 +637,7 @@ impl Pseudo {
610637
path,
611638
protocol,
612639
status: None,
613-
order: pseudo_order,
640+
order: order.unwrap_or_default(),
614641
};
615642

616643
// If the URI includes a scheme component, add it to the pseudo headers
@@ -635,7 +662,7 @@ impl Pseudo {
635662
path: None,
636663
protocol: None,
637664
status: Some(status),
638-
order: None,
665+
order: Default::default(),
639666
}
640667
}
641668

@@ -730,28 +757,26 @@ impl Iterator for Iter {
730757
use crate::hpack::Header::*;
731758

732759
if let Some(ref mut pseudo) = self.pseudo {
733-
if let Some(orders) = pseudo.order.as_ref() {
734-
for pseudo_type in orders {
735-
match pseudo_type {
736-
PseudoOrder::Method => {
737-
if let Some(method) = pseudo.method.take() {
738-
return Some(Method(method));
739-
}
760+
for pseudo_type in pseudo.order.0.iter() {
761+
match pseudo_type {
762+
PseudoOrder::Method => {
763+
if let Some(method) = pseudo.method.take() {
764+
return Some(Method(method));
740765
}
741-
PseudoOrder::Scheme => {
742-
if let Some(scheme) = pseudo.scheme.take() {
743-
return Some(Scheme(scheme));
744-
}
766+
}
767+
PseudoOrder::Scheme => {
768+
if let Some(scheme) = pseudo.scheme.take() {
769+
return Some(Scheme(scheme));
745770
}
746-
PseudoOrder::Authority => {
747-
if let Some(authority) = pseudo.authority.take() {
748-
return Some(Authority(authority));
749-
}
771+
}
772+
PseudoOrder::Authority => {
773+
if let Some(authority) = pseudo.authority.take() {
774+
return Some(Authority(authority));
750775
}
751-
PseudoOrder::Path => {
752-
if let Some(path) = pseudo.path.take() {
753-
return Some(Path(path));
754-
}
776+
}
777+
PseudoOrder::Path => {
778+
if let Some(path) = pseudo.path.take() {
779+
return Some(Path(path));
755780
}
756781
}
757782
}
@@ -827,9 +852,9 @@ impl HeadersFlag {
827852
}
828853

829854
impl Default for HeadersFlag {
830-
/// Returns a `HeadersFlag` value with `END_HEADERS` and `PRIORITY` set.
855+
/// Returns a `HeadersFlag` value with `END_HEADERS` set.
831856
fn default() -> Self {
832-
HeadersFlag(END_HEADERS | PRIORITY)
857+
HeadersFlag(END_HEADERS)
833858
}
834859
}
835860

@@ -1048,6 +1073,8 @@ fn decoded_header_size(name: usize, value: usize) -> usize {
10481073

10491074
#[cfg(test)]
10501075
mod test {
1076+
use std::iter::FromIterator;
1077+
10511078
use super::*;
10521079
use crate::frame;
10531080
use crate::hpack::{huffman, Encoder};

src/frame/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ pub use self::go_away::GoAway;
5353
pub use self::head::{Head, Kind};
5454
pub(crate) use self::headers::PseudoOrder;
5555
pub use self::headers::{
56-
parse_u64, Continuation, Headers, Pseudo, PushPromise, PushPromiseHeaderError,
56+
parse_u64, Continuation, Headers, Pseudo, PseudoOrder, PseudoOrders, PushPromise,
57+
PushPromiseHeaderError,
5758
};
5859
pub use self::ping::Ping;
5960
pub use self::priority::{Priority, StreamDependency};

0 commit comments

Comments
 (0)