use super::error::QuicError;
use super::stream::{RecvStream, SendStream, StreamTracker};
use crate::cx::Cx;
use std::net::SocketAddr;
use std::sync::Arc;
#[derive(Debug)]
pub struct QuicConnection {
inner: quinn::Connection,
tracker: Arc<StreamTracker>,
}
impl QuicConnection {
pub(crate) fn new(inner: quinn::Connection) -> Self {
Self {
inner,
tracker: StreamTracker::new(),
}
}
#[must_use]
pub fn remote_address(&self) -> SocketAddr {
self.inner.remote_address()
}
#[must_use]
pub fn stable_id(&self) -> usize {
self.inner.stable_id()
}
#[must_use]
pub fn alpn_protocol(&self) -> Option<Vec<u8>> {
self.inner.handshake_data().and_then(|data| {
data.downcast::<quinn::crypto::rustls::HandshakeData>()
.ok()
.and_then(|hs| hs.protocol.clone())
})
}
pub async fn open_bi(&self, cx: &Cx) -> Result<(SendStream, RecvStream), QuicError> {
cx.checkpoint()?;
let (send, recv) = self.inner.open_bi().await?;
Ok((
SendStream::new(send, &self.tracker),
RecvStream::new(recv, &self.tracker),
))
}
pub async fn open_uni(&self, cx: &Cx) -> Result<SendStream, QuicError> {
cx.checkpoint()?;
let send = self.inner.open_uni().await?;
Ok(SendStream::new(send, &self.tracker))
}
pub async fn accept_bi(&self, cx: &Cx) -> Result<(SendStream, RecvStream), QuicError> {
cx.checkpoint()?;
let (send, recv) = self.inner.accept_bi().await?;
Ok((
SendStream::new(send, &self.tracker),
RecvStream::new(recv, &self.tracker),
))
}
pub async fn accept_uni(&self, cx: &Cx) -> Result<RecvStream, QuicError> {
cx.checkpoint()?;
let recv = self.inner.accept_uni().await?;
Ok(RecvStream::new(recv, &self.tracker))
}
pub async fn close(&self, cx: &Cx, code: u32, reason: &[u8]) -> Result<(), QuicError> {
cx.checkpoint()?;
self.tracker.mark_closing();
self.inner.close(code.into(), reason);
self.inner.closed().await;
Ok(())
}
pub fn close_immediately(&self, code: u32, reason: &[u8]) {
self.tracker.mark_closing();
self.inner.close(code.into(), reason);
}
#[must_use]
pub fn is_open(&self) -> bool {
!self.tracker.is_closing() && self.inner.close_reason().is_none()
}
pub async fn closed(&self) {
self.inner.closed().await;
}
#[must_use]
pub fn max_datagram_size(&self) -> Option<usize> {
self.inner.max_datagram_size()
}
pub fn send_datagram(&self, data: &[u8]) -> Result<(), QuicError> {
self.inner.send_datagram(data.to_vec().into())?;
Ok(())
}
pub async fn read_datagram(&self, cx: &Cx) -> Result<Vec<u8>, QuicError> {
cx.checkpoint()?;
let data = self.inner.read_datagram().await?;
Ok(data.to_vec())
}
#[must_use]
pub fn rtt(&self) -> std::time::Duration {
self.inner.rtt()
}
#[must_use]
pub fn inner(&self) -> &quinn::Connection {
&self.inner
}
}
impl Drop for QuicConnection {
fn drop(&mut self) {
self.tracker.mark_closing();
}
}