1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! Http2 client

mod connector;
mod pool;
mod simple;
mod stream;

use crate::{error::ConnectionError, error::OperationError, frame};

pub use self::connector::Connector;
pub use self::pool::{Client, ClientBuilder};
pub use self::simple::SimpleClient;
pub use self::stream::{RecvStream, SendStream};

/// Errors which can occur when attempting to handle http2 client connection.
#[derive(thiserror::Error, Debug)]
pub enum ClientError {
    /// Protocol error
    #[error("Protocol error: {0}")]
    Protocol(Box<ConnectionError>),
    /// Operation error
    #[error("Operation error: {0}")]
    Operation(#[from] OperationError),
    /// Http/2 frame codec error
    #[error("Http/2 codec error: {0}")]
    Frame(#[from] frame::FrameError),
    /// Handshake timeout
    #[error("Handshake timeout")]
    HandshakeTimeout,
    /// Connect error
    #[error("Connect error: {0}")]
    Connect(Box<ntex_connect::ConnectError>),
    /// Peer disconnected
    #[error("Peer disconnected err: {0}")]
    Disconnected(#[from] std::io::Error),
}

impl From<ConnectionError> for ClientError {
    fn from(err: ConnectionError) -> Self {
        Self::Protocol(Box::new(err))
    }
}

impl From<ntex_util::channel::Canceled> for ClientError {
    fn from(err: ntex_util::channel::Canceled) -> Self {
        Self::Disconnected(std::io::Error::new(std::io::ErrorKind::Other, err))
    }
}

impl From<ntex_connect::ConnectError> for ClientError {
    fn from(err: ntex_connect::ConnectError) -> Self {
        Self::Connect(Box::new(err))
    }
}

impl Clone for ClientError {
    fn clone(&self) -> Self {
        match self {
            Self::Protocol(err) => Self::Protocol(err.clone()),
            Self::Operation(err) => Self::Operation(err.clone()),
            Self::Frame(err) => Self::Frame(*err),
            Self::HandshakeTimeout => Self::HandshakeTimeout,
            Self::Connect(err) => Self::Connect(err.clone()),
            Self::Disconnected(err) => {
                Self::Disconnected(std::io::Error::new(err.kind(), format!("{}", err)))
            }
        }
    }
}

#[cfg(feature = "unstable")]
pub trait Observer {
    /// New request is prepared
    fn on_request(&mut self, id: frame::StreamId, headers: &mut frame::Headers);

    /// Bytes has been written to memory
    fn on_request_sent(&mut self, id: frame::StreamId);

    /// Payload data has been written to memory
    fn on_request_payload(&mut self, id: frame::StreamId, data: &frame::Data);

    /// Response is received
    fn on_response(&mut self, id: frame::StreamId, headers: &mut frame::Headers);

    /// Payload data has been received
    fn on_response_payload(&mut self, id: frame::StreamId, data: &frame::Data);
}