moq_lite/
session.rs

1use std::{future::Future, pin::Pin, sync::Arc};
2
3use crate::{Error, coding, ietf, lite};
4
5/// The versions of MoQ that are supported by this implementation.
6///
7/// Ordered by preference, with the client's preference taking priority.
8pub const VERSIONS: [coding::Version; 3] = [
9	lite::Version::Draft02.coding(),
10	lite::Version::Draft01.coding(),
11	ietf::Version::Draft14.coding(),
12];
13
14/// The ALPN strings for supported versions.
15pub const ALPNS: [&str; 2] = [lite::ALPN, ietf::ALPN];
16
17/// A MoQ transport session, wrapping a WebTransport connection.
18///
19/// Created via:
20/// - [`crate::Client::connect`] for clients.
21/// - [`crate::Server::accept`] for servers.
22pub struct Session {
23	session: Arc<dyn SessionInner>,
24}
25
26impl Session {
27	pub(super) fn new<S: web_transport_trait::Session>(session: S) -> Self {
28		Self {
29			session: Arc::new(session),
30		}
31	}
32
33	/// Close the underlying transport session.
34	pub fn close(self, err: Error) {
35		self.session.close(err.to_code(), err.to_string().as_ref());
36	}
37
38	/// Block until the transport session is closed.
39	// TODO Remove the Result the next time we make a breaking change.
40	pub async fn closed(&self) -> Result<(), Error> {
41		let err = self.session.closed().await;
42		Err(Error::Transport(err))
43	}
44}
45
46// We use a wrapper type that is dyn-compatible to remove the generic bounds from Session.
47trait SessionInner: Send + Sync {
48	fn close(&self, code: u32, reason: &str);
49	fn closed(&self) -> Pin<Box<dyn Future<Output = Arc<dyn crate::error::SendSyncError>> + Send + '_>>;
50}
51
52impl<S: web_transport_trait::Session> SessionInner for S {
53	fn close(&self, code: u32, reason: &str) {
54		S::close(self, code, reason);
55	}
56
57	fn closed(&self) -> Pin<Box<dyn Future<Output = Arc<dyn crate::error::SendSyncError>> + Send + '_>> {
58		Box::pin(async move { Arc::new(S::closed(self).await) as Arc<dyn crate::error::SendSyncError> })
59	}
60}