Skip to main content

moq_rtc/client/
mod.rs

1//! HTTP-client side: dial a remote WHIP/WHEP endpoint over an SDP exchange.
2//!
3//! Counterpart to [`crate::server`]. Whereas the server accepts POSTed
4//! offers, the client mints the offer with `str0m::Rtc::sdp_api` and POSTs
5//! it to the remote URL. Once the answer arrives the same internal session
6//! driver takes over, so the per-codec bridges and UDP socket loop are shared.
7
8mod whep;
9mod whip;
10
11use std::net::SocketAddr;
12
13use url::Url;
14
15/// Configuration shared by both `client publish` and `client subscribe`.
16#[derive(Clone, Debug, Default)]
17#[non_exhaustive]
18pub struct Config {
19	/// Public UDP socket addresses to advertise as ICE host candidates in
20	/// our outbound offer. Same semantics as [`crate::server::Config::ice_candidates`].
21	pub ice_candidates: Vec<SocketAddr>,
22}
23
24/// Outbound WHIP/WHEP dialer.
25///
26/// Owns a [`reqwest::Client`] reused across calls so connection pooling and
27/// rustls config survive between resources.
28#[derive(Clone)]
29pub struct Client {
30	config: Config,
31	http: reqwest::Client,
32}
33
34impl Client {
35	/// Build a dialer from the shared client [`Config`]. The underlying
36	/// [`reqwest::Client`] (with its connection pool and rustls config) is created
37	/// once here and reused across every [`subscribe`](Self::subscribe) /
38	/// [`publish`](Self::publish) call.
39	pub fn new(config: Config) -> Self {
40		Self {
41			config,
42			http: reqwest::Client::new(),
43		}
44	}
45
46	pub(crate) fn config(&self) -> &Config {
47		&self.config
48	}
49
50	pub(crate) fn http(&self) -> &reqwest::Client {
51		&self.http
52	}
53
54	/// `client subscribe`: pull a remote WHEP feed and publish it as
55	/// `broadcast` on the local origin. Returns once the session is
56	/// running in the background.
57	pub async fn subscribe(&self, url: Url, broadcast: moq_net::broadcast::Producer) -> crate::Result<()> {
58		whep::dial(self, url, broadcast).await
59	}
60
61	/// `client publish`: pull the broadcast at `path` from `origin` and push it to a
62	/// remote WHIP endpoint. Gated on the per-codec re-packetizer.
63	///
64	/// Taking the origin plus path (rather than a resolved [`moq_net::broadcast::Consumer`])
65	/// lets the egress resolve a rendition whose catalog `broadcast` field references a
66	/// sibling broadcast, against the same origin.
67	pub async fn publish(
68		&self,
69		url: Url,
70		origin: moq_net::origin::Consumer,
71		path: impl moq_net::AsPath,
72	) -> crate::Result<()> {
73		whip::dial(self, url, origin, path).await
74	}
75}