Skip to content

Commit 203f177

Browse files
committed
Refactor delay reset queue
1 parent 4e556d0 commit 203f177

File tree

4 files changed

+51
-47
lines changed

4 files changed

+51
-47
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Changes
22

3-
## [1.8.2] - 2025-02-09
3+
## [1.8.4] - 2025-02-10
4+
5+
* Refactor delay reset queue
6+
7+
## [1.8.3] - 2025-02-09
48

59
* Re-calculate delay reset queue
610

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ntex-h2"
3-
version = "1.8.3"
3+
version = "1.8.4"
44
license = "MIT OR Apache-2.0"
55
authors = ["Nikolay Kim <[email protected]>"]
66
description = "An HTTP/2 client and server"

src/connection.rs

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use ntex_bytes::{ByteString, Bytes};
55
use ntex_http::{HeaderMap, Method};
66
use ntex_io::IoRef;
77
use ntex_util::time::{self, now, sleep};
8-
use ntex_util::{channel::pool, future::Either, spawn, HashMap};
8+
use ntex_util::{channel::pool, future::Either, spawn, HashMap, HashSet};
99

1010
use crate::config::{Config, ConfigInner};
1111
use crate::error::{ConnectionError, OperationError, StreamError, StreamErrorInner};
@@ -107,7 +107,7 @@ impl Connection {
107107
streams_count: Cell::new(0),
108108
pings_count: Cell::new(0),
109109
readiness: RefCell::new(VecDeque::new()),
110-
next_stream_id: Cell::new(StreamId::new(1)),
110+
next_stream_id: Cell::new(StreamId::CLIENT),
111111
local_config: config,
112112
local_max_concurrent_streams: Cell::new(None),
113113
local_pending_reset: Default::default(),
@@ -471,10 +471,6 @@ impl RecvHalfConnection {
471471
// if client and no stream, then it was closed
472472
self.encode(frame::Reset::new(id, frame::Reason::STREAM_CLOSED));
473473
Ok(None)
474-
} else if id < self.0.next_stream_id.get() {
475-
Err(Either::Left(ConnectionError::InvalidStreamId(
476-
"Received headers",
477-
)))
478474
} else {
479475
// refuse stream if connection is preparing for disconnect
480476
if self
@@ -525,7 +521,6 @@ impl RecvHalfConnection {
525521
Err(Either::Left(ConnectionError::UnexpectedPseudo("scheme")))
526522
} else {
527523
let stream = StreamRef::new(id, true, Connection(self.0.clone()));
528-
self.0.next_stream_id.set(id);
529524
self.0.streams_count.set(self.0.streams_count.get() + 1);
530525
self.0.streams.borrow_mut().insert(id, stream.clone());
531526
self.0
@@ -868,8 +863,8 @@ async fn ping(st: Connection, timeout: time::Seconds, io: IoRef) {
868863
}
869864
}
870865

871-
const BLOCKS: usize = 6;
872-
const LAST_BLOCK: usize = 5;
866+
const BLOCKS: usize = 5;
867+
const LAST_BLOCK: usize = 4;
873868

874869
#[cfg(not(test))]
875870
const SECS: u64 = 30;
@@ -881,58 +876,67 @@ const ALL_BLOCKS: Duration = Duration::from_secs((BLOCKS as u64) * SECS);
881876

882877
#[derive(Default)]
883878
struct Pending {
884-
blocks: RefCell<[Option<(StreamId, Instant)>; BLOCKS]>,
879+
idx: Cell<u8>,
880+
blocks: RefCell<[Block; BLOCKS]>,
881+
}
882+
883+
#[derive(Debug)]
884+
struct Block {
885+
start_time: Instant,
886+
ids: HashSet<StreamId>,
885887
}
886888

887889
impl Pending {
888890
fn add(&self, id: StreamId) {
889891
let cur = now();
892+
let idx = self.idx.get() as usize;
890893
let mut blocks = self.blocks.borrow_mut();
891894

892-
if let Some(item) = &blocks[0] {
893-
// check if we need to insert new block
894-
if item.1 < (cur - BLOCK_SIZE) {
895-
// shift blocks
896-
let mut i = LAST_BLOCK - 1;
897-
loop {
898-
blocks[i + 1] = blocks[i];
899-
if i == 0 {
900-
break;
901-
}
902-
i -= 1;
903-
}
904-
// insert new item
905-
blocks[0] = Some((id, cur));
906-
}
907-
} else {
895+
// check if we need to insert new block
896+
if blocks[idx].start_time < (cur - BLOCK_SIZE) {
897+
// shift blocks
898+
let idx = if idx == 0 { LAST_BLOCK } else { idx - 1 };
908899
// insert new item
909-
blocks[0] = Some((id, cur));
900+
blocks[idx].start_time = cur;
901+
blocks[idx].ids.clear();
902+
blocks[idx].ids.insert(id);
903+
self.idx.set(idx as u8);
910904
}
911905
}
912906

913907
fn is_pending(&self, id: StreamId) -> bool {
914-
let mut blocks = self.blocks.borrow_mut();
915-
let mut idx = LAST_BLOCK;
916-
let mut cur = now() - ALL_BLOCKS;
908+
let blocks = self.blocks.borrow_mut();
909+
910+
let max = now() - ALL_BLOCKS;
911+
let mut idx = self.idx.get() as usize;
912+
917913
loop {
918-
if let Some(item) = &blocks[idx] {
919-
if item.1 < cur {
920-
blocks[idx] = None;
921-
} else {
922-
return id >= item.0;
923-
}
924-
} else {
925-
cur += BLOCK_SIZE;
914+
let item = &blocks[idx];
915+
if item.start_time < max {
916+
break;
917+
} else if item.ids.contains(&id) {
918+
return true;
926919
}
927-
if idx == 0 {
920+
idx += 1;
921+
if idx == BLOCKS {
922+
idx = 0;
923+
} else if idx == self.idx.get() as usize {
928924
break;
929925
}
930-
idx -= 1;
931926
}
932927
false
933928
}
934929
}
935930

931+
impl Default for Block {
932+
fn default() -> Self {
933+
Self {
934+
ids: HashSet::default(),
935+
start_time: now() - ALL_BLOCKS,
936+
}
937+
}
938+
}
939+
936940
#[cfg(test)]
937941
mod tests {
938942
use ntex::http::{test::server as test_server, HeaderMap, Method};
@@ -1027,7 +1031,7 @@ mod tests {
10271031
let res = get_reset(io.recv(&codec).await.unwrap().unwrap());
10281032
assert_eq!(res.reason(), Reason::STREAM_CLOSED);
10291033

1030-
sleep(Millis(1100)).await;
1034+
sleep(Millis(5100)).await;
10311035

10321036
// prev closed stream
10331037
io.send(pl.into(), &codec).await.unwrap();

src/frame/stream_id.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ impl StreamId {
2626
/// The maximum allowed stream ID.
2727
pub const MAX: StreamId = StreamId(u32::MAX >> 1);
2828

29-
pub(crate) const fn new(src: u32) -> StreamId {
30-
StreamId(src)
31-
}
32-
3329
/// Parse the stream ID
3430
#[inline]
3531
pub fn parse(buf: &[u8]) -> (StreamId, bool) {

0 commit comments

Comments
 (0)