Skip to main content

moq_lite/
session.rs

1use std::{future::Future, pin::Pin};
2
3use crate::Error;
4
5/// A MoQ transport session, wrapping a WebTransport connection.
6///
7/// Created via:
8/// - [`crate::Client::connect`] for clients.
9/// - [`crate::Server::accept`] for servers.
10pub struct Session {
11	session: Box<dyn SessionInner>,
12	closed: bool,
13}
14
15impl Session {
16	pub(super) fn new<S: web_transport_trait::Session>(session: S) -> Self {
17		Self {
18			session: Box::new(session),
19			closed: false,
20		}
21	}
22
23	/// Close the underlying transport session.
24	pub fn close(&mut self, err: Error) {
25		if self.closed {
26			return;
27		}
28		self.closed = true;
29		self.session.close(err.to_code(), err.to_string().as_ref());
30	}
31
32	/// Block until the transport session is closed.
33	// TODO Remove the Result the next time we make a breaking change.
34	pub async fn closed(&self) -> Result<(), Error> {
35		self.session.closed().await;
36		Err(Error::Transport)
37	}
38}
39
40impl Drop for Session {
41	fn drop(&mut self) {
42		if !self.closed {
43			self.session.close(Error::Cancel.to_code(), "dropped");
44		}
45	}
46}
47
48// We use a wrapper type that is dyn-compatible to remove the generic bounds from Session.
49trait SessionInner: Send + Sync {
50	fn close(&self, code: u32, reason: &str);
51	fn closed(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>;
52}
53
54impl<S: web_transport_trait::Session> SessionInner for S {
55	fn close(&self, code: u32, reason: &str) {
56		S::close(self, code, reason);
57	}
58
59	fn closed(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
60		Box::pin(async move {
61			let _ = S::closed(self).await;
62		})
63	}
64}