Skip to content

Commit 6592063

Browse files
authored
Better error handling (#37)
1 parent 0c4c74d commit 6592063

11 files changed

Lines changed: 179 additions & 66 deletions

File tree

.github/workflows/CI.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,17 @@ jobs:
6969
if: matrix.rust == 'nightly' || matrix.rust == 'beta'
7070
with:
7171
command: build
72+
args: --features=ntex-net/tokio
7273

7374
- name: Run lib tests and doc tests
7475
uses: actions-rs/cargo@v1
7576
if: matrix.rust == 'nightly' || matrix.rust == 'beta'
7677
with:
7778
command: test
79+
args: --features=ntex-net/tokio
7880

7981
- name: Generate code coverage
80-
run: cargo llvm-cov --no-report
82+
run: cargo llvm-cov --no-report --features=ntex-net/tokio
8183
if: matrix.rust == 'stable'
8284

8385
#- name: Run integration tests
@@ -130,3 +132,4 @@ jobs:
130132
uses: actions-rs/cargo@v1
131133
with:
132134
command: check
135+
args: --features=ntex-net/tokio

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changes
22

3+
## [1.2.0] - 2024-10-16
4+
5+
* Better error handling
6+
37
## [1.1.0] - 2024-08-12
48

59
* Server graceful shutdown support

Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ntex-h2"
3-
version = "1.1.0"
3+
version = "1.2.0"
44
license = "MIT OR Apache-2.0"
55
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
66
description = "An HTTP/2 client and server"
@@ -46,9 +46,8 @@ walkdir = "2.3.2"
4646
serde = "1.0"
4747
serde_json = "1.0"
4848

49-
ntex = { version = "2", features = ["openssl", "tokio"] }
49+
ntex = { version = "2", features = ["openssl"] }
5050
ntex-tls = { version = "2", features = ["openssl"] }
51-
ntex-net = { version = "2", features = ["tokio"] }
5251
openssl = "0.10"
5352

5453
# Examples

src/client/connector.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use std::{cell::Cell, marker::PhantomData, ops};
1+
use std::{marker::PhantomData, ops};
22

3-
use ntex_bytes::{ByteString, PoolId, PoolRef};
3+
use ntex_bytes::{ByteString, PoolId};
44
use ntex_http::uri::Scheme;
55
use ntex_io::IoBoxed;
66
use ntex_net::connect::{self as connect, Address, Connect, Connector as DefaultConnector};
@@ -15,7 +15,6 @@ pub struct Connector<A: Address, T> {
1515
connector: Pipeline<T>,
1616
config: Config,
1717
scheme: Scheme,
18-
pub(super) pool: Cell<PoolRef>,
1918

2019
_t: PhantomData<A>,
2120
}
@@ -35,7 +34,6 @@ where
3534
connector: Pipeline::new(connector.into_service()),
3635
config: Config::client(),
3736
scheme: Scheme::HTTP,
38-
pool: Cell::new(PoolId::P5.pool_ref()),
3937
_t: PhantomData,
4038
}
4139
}
@@ -51,7 +49,6 @@ where
5149
connector: DefaultConnector::default().into(),
5250
config: Config::client(),
5351
scheme: Scheme::HTTP,
54-
pool: Cell::new(PoolId::P5.pool_ref()),
5552
_t: PhantomData,
5653
}
5754
}
@@ -82,12 +79,13 @@ where
8279
self
8380
}
8481

82+
#[doc(hidden)]
83+
#[deprecated]
8584
/// Set memory pool.
8685
///
8786
/// Use specified memory pool for memory allocations. By default P5
8887
/// memory pool is used.
89-
pub fn memory_pool(&mut self, id: PoolId) -> &mut Self {
90-
self.pool.set(id.pool_ref());
88+
pub fn memory_pool(&mut self, _: PoolId) -> &mut Self {
9189
self
9290
}
9391

@@ -102,7 +100,6 @@ where
102100
connector: connector.into_service().into(),
103101
config: self.config.clone(),
104102
scheme: self.scheme.clone(),
105-
pool: self.pool.clone(),
106103
_t: PhantomData,
107104
}
108105
}

src/client/simple.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ impl SimpleClient {
7171
}))
7272
}
7373

74+
#[inline]
75+
/// Get io tag
76+
pub fn tag(&self) -> &'static str {
77+
self.0.con.tag()
78+
}
79+
7480
#[inline]
7581
/// Send request to the peer
7682
pub async fn send(

src/client/stream.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use std::{cell::RefCell, collections::VecDeque, fmt, future::poll_fn, pin::Pin,
44
use ntex_bytes::Bytes;
55
use ntex_http::HeaderMap;
66
use ntex_service::{Service, ServiceCtx};
7-
use ntex_util::future::Either;
8-
use ntex_util::{task::LocalWaker, HashMap, Stream as FutStream};
7+
use ntex_util::{future::Either, task::LocalWaker, HashMap, Stream as FutStream};
98

109
use crate::error::OperationError;
1110
use crate::frame::{Reason, StreamId, WindowSize};
@@ -75,21 +74,30 @@ impl Drop for SendStream {
7574

7675
impl SendStream {
7776
#[inline]
77+
/// Get stream id
7878
pub fn id(&self) -> StreamId {
7979
self.0.id()
8080
}
8181

82+
#[inline]
83+
/// Get io tag
84+
pub fn tag(&self) -> &'static str {
85+
self.0.tag()
86+
}
87+
8288
#[inline]
8389
pub fn stream(&self) -> &StreamRef {
8490
&self.0
8591
}
8692

8793
#[inline]
94+
/// Get available capacity
8895
pub fn available_send_capacity(&self) -> WindowSize {
8996
self.0.available_send_capacity()
9097
}
9198

9299
#[inline]
100+
/// Wait for available capacity
93101
pub async fn send_capacity(&self) -> Result<WindowSize, OperationError> {
94102
self.0.send_capacity().await
95103
}
@@ -101,6 +109,7 @@ impl SendStream {
101109
}
102110

103111
#[inline]
112+
/// Send trailers
104113
pub fn send_trailers(&self, map: HeaderMap) {
105114
self.0.send_trailers(map)
106115
}
@@ -130,10 +139,17 @@ pub struct RecvStream(StreamRef, InflightStorage);
130139

131140
impl RecvStream {
132141
#[inline]
142+
/// Get stream id
133143
pub fn id(&self) -> StreamId {
134144
self.0.id()
135145
}
136146

147+
#[inline]
148+
/// Get io tag
149+
pub fn tag(&self) -> &'static str {
150+
self.0.tag()
151+
}
152+
137153
#[inline]
138154
pub fn stream(&self) -> &StreamRef {
139155
&self.0
@@ -148,23 +164,17 @@ impl RecvStream {
148164
/// the current task for wakeup if the value is not yet available,
149165
/// and returning None if the stream is exhausted.
150166
pub fn poll_recv(&self, cx: &mut Context<'_>) -> Poll<Option<Message>> {
151-
let mut inner = self.1 .0.inflight.borrow_mut();
152-
if let Some(inflight) = inner.get_mut(&self.0.id()) {
167+
if let Some(inflight) = self.1 .0.inflight.borrow_mut().get_mut(&self.0.id()) {
153168
if let Some(msg) = inflight.pop() {
154-
let to_remove = match msg.kind() {
155-
MessageKind::Headers { eof, .. } => *eof,
156-
MessageKind::Eof(..) | MessageKind::Disconnect(..) => true,
157-
_ => false,
158-
};
159-
if to_remove {
160-
inner.remove(&self.0.id());
161-
}
162169
Poll::Ready(Some(msg))
170+
} else if self.0.recv_state().is_closed() {
171+
Poll::Ready(None)
163172
} else {
164173
inflight.waker.register(cx.waker());
165174
Poll::Pending
166175
}
167176
} else {
177+
log::warn!("Stream does not exists, {:?}", self.0.id());
168178
Poll::Ready(None)
169179
}
170180
}
@@ -207,11 +217,14 @@ impl Service<Message> for HandleService {
207217
MessageKind::Eof(..) | MessageKind::Disconnect(..) => true,
208218
_ => false,
209219
};
220+
inflight.push(msg);
221+
210222
if eof {
211223
self.0.notify(id);
212224
log::debug!("Stream {:?} is closed, notify", id);
213225
}
214-
inflight.push(msg);
226+
} else {
227+
log::error!("Received message for unknown stream, {:?}", msg);
215228
}
216229
Ok(())
217230
}

src/config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl Config {
8080
let dispatcher_config = DispatcherConfig::default();
8181
dispatcher_config
8282
.set_keepalive_timeout(Seconds(0))
83-
.set_disconnect_timeout(Seconds(3))
83+
.set_disconnect_timeout(Seconds(1))
8484
.set_frame_read_rate(Seconds(1), Seconds::ZERO, 256);
8585

8686
Config(Rc::new(ConfigInner {
@@ -308,7 +308,7 @@ impl Config {
308308
///
309309
/// To disable timeout set value to 0.
310310
///
311-
/// By default disconnect timeout is set to 3 seconds.
311+
/// By default disconnect timeout is set to 1 seconds.
312312
pub fn disconnect_timeout(&self, val: Seconds) -> &Self {
313313
self.0.dispatcher_config.set_disconnect_timeout(val);
314314
self

src/connection.rs

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ impl Connection {
138138
&self.0.io
139139
}
140140

141+
pub(crate) fn tag(&self) -> &'static str {
142+
self.0.io.tag()
143+
}
144+
141145
pub(crate) fn codec(&self) -> &Codec {
142146
&self.0.codec
143147
}
@@ -263,10 +267,13 @@ impl Connection {
263267

264268
pub(crate) fn disconnect_when_ready(&self) {
265269
if self.0.streams.borrow().is_empty() {
266-
log::debug!("All streams are closed, disconnecting");
270+
log::trace!("{}: All streams are closed, disconnecting", self.tag());
267271
self.0.io.close();
268272
} else {
269-
log::debug!("Not all streams are closed, set disconnect flag");
273+
log::trace!(
274+
"{}: Not all streams are closed, set disconnect flag",
275+
self.tag()
276+
);
270277
self.set_flags(ConnectionFlags::DISCONNECT_WHEN_READY);
271278
}
272279
}
@@ -282,7 +289,10 @@ impl Connection {
282289
self.check_error()?;
283290

284291
if !self.can_create_new_stream() {
285-
log::warn!("Cannot create new stream, waiting for available streams");
292+
log::warn!(
293+
"{}: Cannot create new stream, waiting for available streams",
294+
self.tag()
295+
);
286296
self.ready().await?
287297
}
288298

@@ -326,7 +336,12 @@ impl Connection {
326336
let empty = {
327337
let mut streams = self.0.streams.borrow_mut();
328338
if let Some(stream) = streams.remove(&id) {
329-
log::trace!("Dropping stream {:?} remote: {:?}", id, stream.is_remote());
339+
log::trace!(
340+
"{}: Dropping stream {:?} remote: {:?}",
341+
self.tag(),
342+
id,
343+
stream.is_remote()
344+
);
330345
if stream.is_remote() {
331346
self.0
332347
.active_remote_streams
@@ -352,7 +367,7 @@ impl Connection {
352367

353368
// Close connection
354369
if empty && flags.contains(ConnectionFlags::DISCONNECT_WHEN_READY) {
355-
log::debug!("All streams are closed, disconnecting");
370+
log::trace!("{}: All streams are closed, disconnecting", self.tag());
356371
self.0.io.close();
357372
return;
358373
}
@@ -379,6 +394,10 @@ impl Connection {
379394
}
380395

381396
impl RecvHalfConnection {
397+
pub(crate) fn tag(&self) -> &'static str {
398+
self.0.io.tag()
399+
}
400+
382401
fn query(&self, id: StreamId) -> Option<StreamRef> {
383402
self.0.streams.borrow_mut().get(&id).cloned()
384403
}
@@ -614,7 +633,7 @@ impl RecvHalfConnection {
614633
&self,
615634
frm: frame::WindowUpdate,
616635
) -> Result<(), Either<ConnectionError, StreamErrorInner>> {
617-
log::trace!("processing incoming {:#?}", frm);
636+
log::trace!("{}: processing incoming {:#?}", self.tag(), frm);
618637

619638
if frm.stream_id().is_zero() {
620639
if frm.size_increment() == 0 {
@@ -658,7 +677,7 @@ impl RecvHalfConnection {
658677
&self,
659678
frm: frame::Reset,
660679
) -> Result<(), Either<ConnectionError, StreamErrorInner>> {
661-
log::trace!("processing incoming {:#?}", frm);
680+
log::trace!("{}: processing incoming {:#?}", self.tag(), frm);
662681

663682
if frm.stream_id().is_zero() {
664683
Err(Either::Left(ConnectionError::UnknownStream("RST_STREAM")))
@@ -688,7 +707,8 @@ impl RecvHalfConnection {
688707
data: &Bytes,
689708
) -> HashMap<StreamId, StreamRef> {
690709
log::trace!(
691-
"processing go away with reason: {:?}, data: {:?}",
710+
"{}: processing go away with reason: {:?}, data: {:?}",
711+
self.tag(),
692712
reason,
693713
data.slice(..std::cmp::min(data.len(), 20))
694714
);
@@ -801,7 +821,7 @@ async fn delay_drop_task(state: Connection) {
801821
loop {
802822
if let Some(item) = queue.front() {
803823
if item.1 <= now {
804-
log::trace!("dropping {:?} after delay", item.0);
824+
log::trace!("{}: dropping {:?} after delay", state.tag(), item.0);
805825
ids.remove(&item.0);
806826
queue.pop_front();
807827
} else {
@@ -825,7 +845,10 @@ async fn ping(st: Connection, timeout: time::Seconds, io: IoRef) {
825845
st.set_flags(ConnectionFlags::RECV_PONG);
826846
loop {
827847
if st.is_closed() {
828-
log::debug!("http client connection is closed, stopping keep-alive task");
848+
log::trace!(
849+
"{}: http client connection is closed, stopping keep-alive task",
850+
st.tag()
851+
);
829852
break;
830853
}
831854
sleep(keepalive).await;

0 commit comments

Comments
 (0)