diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6abf65b..1768848 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,6 +22,44 @@ jobs: - run: cargo fmt --all --check + test: + name: Test + needs: [style] + runs-on: ubuntu-latest + env: + RUSTFLAGS: -Dwarnings + strategy: + matrix: + rust: + - beta + - stable + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust (${{ matrix.rust }}) + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + + - name: Install libssl-dev + run: sudo apt-get update && sudo apt-get install libssl-dev + - name: Build without unstable flag + run: cargo build + + - name: Check with unstable flag + run: cargo check --features unstable + + - name: Run lib tests and doc tests + run: cargo test + + - name: Run integration tests + run: cargo test -p h2-tests + + - name: Run h2spec + run: ./ci/h2spec.sh + if: matrix.rust == 'stable' + #clippy_check: # runs-on: ubuntu-latest # steps: @@ -49,9 +87,12 @@ jobs: with: toolchain: ${{ steps.msrv.outputs.version }} - - name: Make sure tokio 1.38.1 is used for MSRV + - name: Pin some dependencies for MSRV run: | - cargo update cargo update --package tokio --precise 1.38.1 + cargo update --package tokio-util --precise 0.7.11 + cargo update --package hashbrown --precise 0.15.0 + + - run: cargo check -p h2 - run: cargo check -p rh2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4abbf24..f5dc746 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,31 +1,10 @@ -# 0.4.5 (May 17, 2024) - -* Fix race condition that sometimes hung connections during shutdown. -* Fix pseudo header construction for CONNECT and OPTIONS requests. - -# 0.4.4 (April 3, 2024) +# 0.3.26 (April 3, 2024) * Limit number of CONTINUATION frames for misbehaving connections. -# 0.4.3 (March 15, 2024) - -* Fix flow control limits to not apply until receiving SETTINGS ack. -* Fix not returning an error if IO ended without `close_notify`. -* Improve performance of decoding many headers. - -# 0.4.2 (January 17th, 2024) - -* Limit error resets for misbehaving connections. -* Fix selecting MAX_CONCURRENT_STREAMS value if no value is advertised initially. - -# 0.4.1 (January 8, 2024) - -* Fix assigning connection capacity which could starve streams in some instances. - -# 0.4.0 (November 15, 2023) +# 0.3.25 (March 15, 2024) -* Update to `http` 1.0. -* Remove deprecated `Server::poll_close()`. +* Improve performance decoding many headers. # 0.3.24 (January 17, 2024) diff --git a/src/codec/framed_write.rs b/src/codec/framed_write.rs index c88af02..a94647b 100644 --- a/src/codec/framed_write.rs +++ b/src/codec/framed_write.rs @@ -133,7 +133,7 @@ where loop { while !self.encoder.is_empty() { - match self.encoder.next { + let n = match self.encoder.next { Some(Next::Data(ref mut frame)) => { tracing::trace!(queued_data_frame = true); let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut()); @@ -148,6 +148,12 @@ where ))? } }; + if n == 0 { + return Poll::Ready(Err(io::Error::new( + io::ErrorKind::WriteZero, + "failed to write frame to socket", + ))); + } } match self.encoder.unset_frame() { diff --git a/src/frame/headers.rs b/src/frame/headers.rs index 4a73a1a..68c81bc 100644 --- a/src/frame/headers.rs +++ b/src/frame/headers.rs @@ -1052,6 +1052,8 @@ fn decoded_header_size(name: usize, value: usize) -> usize { #[cfg(test)] mod test { + use std::iter::FromIterator; + use super::*; use crate::frame; use crate::hpack::{huffman, Encoder}; diff --git a/src/proto/streams/streams.rs b/src/proto/streams/streams.rs index ead3929..e632b77 100644 --- a/src/proto/streams/streams.rs +++ b/src/proto/streams/streams.rs @@ -1599,6 +1599,9 @@ impl Actions { // Reset the stream. self.send .send_reset(reason, initiator, buffer, stream, counts, &mut self.task); + self.recv.enqueue_reset_expiration(stream, counts); + // if a RecvStream is parked, ensure it's notified + stream.notify_recv(); Ok(()) } else { tracing::warn!( diff --git a/tests/h2-tests/tests/prioritization.rs b/tests/h2-tests/tests/prioritization.rs index dd4ed9f..11d2c2c 100644 --- a/tests/h2-tests/tests/prioritization.rs +++ b/tests/h2-tests/tests/prioritization.rs @@ -1,3 +1,4 @@ +use futures::future::{join, select}; use futures::{pin_mut, FutureExt, StreamExt}; use h2_support::prelude::*; diff --git a/tests/h2-tests/tests/server.rs b/tests/h2-tests/tests/server.rs index 91c8d40..9191640 100644 --- a/tests/h2-tests/tests/server.rs +++ b/tests/h2-tests/tests/server.rs @@ -1,5 +1,6 @@ #![deny(warnings)] +use futures::future::join; use futures::StreamExt; use h2_support::prelude::*; use tokio::io::AsyncWriteExt; diff --git a/tests/h2-tests/tests/stream_states.rs b/tests/h2-tests/tests/stream_states.rs index 9a377d7..d511f92 100644 --- a/tests/h2-tests/tests/stream_states.rs +++ b/tests/h2-tests/tests/stream_states.rs @@ -1,6 +1,6 @@ #![deny(warnings)] -use futures::future::lazy; +use futures::future::{join, join3, lazy, try_join}; use futures::{FutureExt, StreamExt, TryStreamExt}; use h2_support::prelude::*; use h2_support::util::yield_once; @@ -536,7 +536,12 @@ async fn recv_next_stream_id_updated_by_malformed_headers() { client.recv_frame(frames::go_away(1).protocol_error()).await; }; let srv = async move { - let mut srv = server::handshake(io).await.expect("handshake"); + let mut srv = server::Builder::new() + // forget the bad stream immediately + .max_concurrent_reset_streams(0) + .handshake::<_, Bytes>(io) + .await + .expect("handshake"); let res = srv.next().await.unwrap(); let err = res.unwrap_err(); assert_eq!(err.reason(), Some(h2::Reason::PROTOCOL_ERROR));