Skip to main content

http3_datagram/
datagram_handler.rs

1//! Traits which define the user API for datagrams.
2//! These traits are implemented for the client and server types in the `http3` crate.
3
4use std::{error::Error, fmt::Display, future::poll_fn, marker::PhantomData, sync::Arc};
5
6use bytes::Buf;
7use http3::{
8    ConnectionState, SharedState,
9    error::{ConnectionError, StreamError, connection_error_creators::CloseStream},
10    quic::{self, StreamId},
11};
12
13use crate::{
14    datagram::Datagram,
15    quic_traits::{DatagramConnectionExt, RecvDatagram, SendDatagram, SendDatagramErrorIncoming},
16};
17
18/// Gives the ability to send datagrams.
19#[derive(Debug)]
20pub struct DatagramSender<H: SendDatagram<B>, B: Buf> {
21    pub(crate) handler: H,
22    pub(crate) _marker: PhantomData<B>,
23    pub(crate) shared_state: Arc<SharedState>,
24    pub(crate) stream_id: StreamId,
25}
26
27impl<H, B> ConnectionState for DatagramSender<H, B>
28where
29    H: SendDatagram<B>,
30    B: Buf,
31{
32    fn shared_state(&self) -> &SharedState {
33        self.shared_state.as_ref()
34    }
35}
36
37impl<H, B> DatagramSender<H, B>
38where
39    H: SendDatagram<B>,
40    B: Buf,
41{
42    /// Sends a datagram
43    pub fn send_datagram(&mut self, data: B) -> Result<(), SendDatagramError> {
44        let encoded_datagram = Datagram::new(self.stream_id, data);
45        match self.handler.send_datagram(encoded_datagram.encode()) {
46            Ok(()) => Ok(()),
47            Err(e) => Err(self.handle_send_datagram_error(e)),
48        }
49    }
50
51    fn handle_send_datagram_error(
52        &mut self,
53        error: SendDatagramErrorIncoming,
54    ) -> SendDatagramError {
55        match error {
56            SendDatagramErrorIncoming::NotAvailable => SendDatagramError::NotAvailable,
57            SendDatagramErrorIncoming::TooLarge => SendDatagramError::TooLarge,
58            SendDatagramErrorIncoming::ConnectionError(error) => {
59                self.set_conn_error_and_wake(error.clone());
60                SendDatagramError::ConnectionError(ConnectionError::Remote(error))
61            }
62        }
63    }
64}
65
66#[derive(Debug)]
67pub struct DatagramReader<H: RecvDatagram> {
68    pub(crate) handler: H,
69    pub(crate) shared_state: Arc<SharedState>,
70}
71
72impl<H> ConnectionState for DatagramReader<H>
73where
74    H: RecvDatagram,
75{
76    fn shared_state(&self) -> &SharedState {
77        self.shared_state.as_ref()
78    }
79}
80
81impl<H> CloseStream for DatagramReader<H> where H: RecvDatagram {}
82
83impl<H> DatagramReader<H>
84where
85    H: RecvDatagram,
86{
87    /// Reads an incoming datagram
88    pub async fn read_datagram(&mut self) -> Result<Datagram<H::Buffer>, StreamError> {
89        match poll_fn(|cx| self.handler.poll_incoming_datagram(cx)).await {
90            Ok(datagram) => Datagram::decode(datagram)
91                .map_err(|err| self.handle_connection_error_on_stream(err)),
92            Err(err) => Err(self.handle_quic_stream_error(
93                quic::StreamErrorIncoming::ConnectionErrorIncoming {
94                    connection_error: err,
95                },
96            )),
97        }
98    }
99}
100
101pub trait HandleDatagramsExt<C, B>: ConnectionState
102where
103    B: Buf,
104    C: quic::Connection<B> + DatagramConnectionExt<B>,
105{
106    /// Sends a datagram
107    fn get_datagram_sender(&self, stream_id: StreamId)
108    -> DatagramSender<C::SendDatagramHandler, B>;
109    /// Reads an incoming datagram
110    fn get_datagram_reader(&self) -> DatagramReader<C::RecvDatagramHandler>;
111}
112
113/// Types of errors when sending a datagram.
114#[derive(Debug)]
115#[non_exhaustive]
116pub enum SendDatagramError {
117    /// The peer is not accepting datagrams on the quic layer
118    ///
119    /// This can be because the peer does not support it or disabled it or any other reason.
120    #[non_exhaustive]
121    NotAvailable,
122    /// The datagram is too large to send
123    #[non_exhaustive]
124    TooLarge,
125    /// Connection error
126    #[non_exhaustive]
127    ConnectionError(ConnectionError),
128}
129
130impl Display for SendDatagramError {
131    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132        match self {
133            SendDatagramError::NotAvailable => write!(f, "Datagrams are not available"),
134            SendDatagramError::TooLarge => write!(f, "Datagram is too large"),
135            SendDatagramError::ConnectionError(e) => write!(f, "Connection error: {}", e),
136        }
137    }
138}
139
140impl Error for SendDatagramError {}