pub(crate) mod driver;
pub(crate) mod ice_gatherer;
use log::error;
use std::collections::{HashMap, HashSet};
use std::net::ToSocketAddrs;
use std::sync::Arc;
use std::time::Instant;
use crate::data_channel::{DataChannel, DataChannelEvent, DataChannelImpl};
use crate::media_stream::{track_local::TrackLocal, track_remote::TrackRemote};
use crate::rtp_transceiver::{RtpReceiver, RtpSender, RtpTransceiver, RtpTransceiverImpl};
use crate::runtime::{JoinHandle, Runtime, default_runtime};
use crate::runtime::{Mutex, Sender, channel};
use driver::{
DATA_CHANNEL_EVENT_CHANNEL_CAPACITY, PEER_CONNECTION_DRIVER_EVENT_CHANNEL_CAPACITY,
PeerConnectionDriver,
};
use ice_gatherer::RTCIceGatherOptions;
use ice_gatherer::RTCIceGatherer;
use rtc::data_channel::{RTCDataChannelId, RTCDataChannelInit};
use rtc::peer_connection::RTCPeerConnectionBuilder;
use rtc::peer_connection::configuration::{RTCAnswerOptions, RTCOfferOptions};
use rtc::rtp_transceiver::rtp_sender::RtpCodecKind;
use rtc::rtp_transceiver::{RTCRtpTransceiverId, RTCRtpTransceiverInit};
use rtc::sansio::Protocol;
use rtc::shared::error::{Error, Result};
use rtc::statistics::StatsSelector;
use rtc::statistics::report::RTCStatsReport;
use crate::media_stream::track_local::static_rtp::TrackLocalStaticRTP;
use crate::media_stream::track_remote::TrackRemoteEvent;
use crate::peer_connection::driver::PeerConnectionDriverEvent;
use crate::rtp_transceiver::rtp_sender::RtpSenderImpl;
pub use rtc::interceptor::{Interceptor, NoopInterceptor, Registry};
use rtc::media_stream::MediaStreamTrackId;
pub use rtc::peer_connection::{
RTCPeerConnection,
certificate::RTCCertificate,
configuration::{
RTCBundlePolicy, RTCConfiguration, RTCConfigurationBuilder, RTCIceServer,
RTCIceTransportPolicy, RTCRtcpMuxPolicy, interceptor_registry::*,
media_engine::MediaEngine, setting_engine::SettingEngine,
},
event::{
RTCDataChannelEvent, RTCPeerConnectionEvent, RTCPeerConnectionIceErrorEvent,
RTCPeerConnectionIceEvent, RTCTrackEvent,
},
sdp::{RTCSdpType, RTCSessionDescription},
state::{
RTCIceConnectionState, RTCIceGatheringState, RTCPeerConnectionState, RTCSignalingState,
},
transport::{RTCIceCandidate, RTCIceCandidateInit, RTCIceCandidateType, RTCIceProtocol},
};
#[async_trait::async_trait]
pub trait PeerConnectionEventHandler: Send + Sync + 'static {
async fn on_negotiation_needed(&self) {}
async fn on_ice_candidate(&self, _event: RTCPeerConnectionIceEvent) {}
async fn on_ice_candidate_error(&self, _event: RTCPeerConnectionIceErrorEvent) {}
async fn on_signaling_state_change(&self, _state: RTCSignalingState) {}
async fn on_ice_connection_state_change(&self, _state: RTCIceConnectionState) {}
async fn on_ice_gathering_state_change(&self, _state: RTCIceGatheringState) {}
async fn on_connection_state_change(&self, _state: RTCPeerConnectionState) {}
async fn on_data_channel(&self, _data_channel: Arc<dyn DataChannel>) {}
async fn on_track(&self, _track: Arc<dyn TrackRemote>) {}
}
pub struct PeerConnectionBuilder<A: ToSocketAddrs, I = NoopInterceptor>
where
I: Interceptor,
{
builder: RTCPeerConnectionBuilder<I>,
runtime: Option<Arc<dyn Runtime>>,
handler: Option<Arc<dyn PeerConnectionEventHandler>>,
udp_addrs: Vec<A>,
tcp_addrs: Vec<A>,
}
impl<A: ToSocketAddrs> Default for PeerConnectionBuilder<A, NoopInterceptor> {
fn default() -> Self {
Self {
builder: RTCPeerConnectionBuilder::new(),
runtime: None,
handler: None,
udp_addrs: vec![],
tcp_addrs: vec![],
}
}
}
impl<A: ToSocketAddrs> PeerConnectionBuilder<A, NoopInterceptor> {
pub fn new() -> Self {
Self::default()
}
}
impl<A: ToSocketAddrs, I> PeerConnectionBuilder<A, I>
where
I: Interceptor,
{
pub fn with_configuration(mut self, configuration: RTCConfiguration) -> Self {
self.builder = self.builder.with_configuration(configuration);
self
}
pub fn with_media_engine(mut self, media_engine: MediaEngine) -> Self {
self.builder = self.builder.with_media_engine(media_engine);
self
}
pub fn with_setting_engine(mut self, setting_engine: SettingEngine) -> Self {
self.builder = self.builder.with_setting_engine(setting_engine);
self
}
pub fn with_interceptor_registry<P>(
self,
interceptor_registry: Registry<P>,
) -> PeerConnectionBuilder<A, P>
where
P: Interceptor,
{
PeerConnectionBuilder {
builder: self.builder.with_interceptor_registry(interceptor_registry),
runtime: self.runtime,
handler: self.handler,
udp_addrs: self.udp_addrs,
tcp_addrs: self.tcp_addrs,
}
}
pub fn with_runtime(mut self, runtime: Arc<dyn Runtime>) -> Self {
self.runtime = Some(runtime);
self
}
pub fn with_handler(mut self, handler: Arc<dyn PeerConnectionEventHandler>) -> Self {
self.handler = Some(handler);
self
}
pub fn with_udp_addrs(mut self, udp_addrs: Vec<A>) -> Self {
self.udp_addrs = udp_addrs;
self
}
pub fn with_tcp_addrs(mut self, tcp_addrs: Vec<A>) -> Self {
self.tcp_addrs = tcp_addrs;
self
}
pub async fn build(self) -> Result<impl PeerConnection> {
let runtime = if let Some(runtime) = self.runtime {
runtime
} else {
default_runtime().ok_or_else(|| std::io::Error::other("no async runtime found"))?
};
let core = self.builder.build()?;
let configuration = core.get_configuration();
let opts = RTCIceGatherOptions {
ice_servers: configuration.ice_servers().to_vec(),
ice_gather_policy: configuration.ice_transport_policy(),
};
PeerConnectionImpl::new(
core,
runtime,
self.handler
.ok_or_else(|| std::io::Error::other("no event handler found"))?,
opts,
self.udp_addrs,
self.tcp_addrs,
)
.await
}
}
#[async_trait::async_trait]
pub trait PeerConnection: Send + Sync + 'static {
async fn close(&self) -> Result<()>;
async fn create_offer(&self, options: Option<RTCOfferOptions>)
-> Result<RTCSessionDescription>;
async fn create_answer(
&self,
options: Option<RTCAnswerOptions>,
) -> Result<RTCSessionDescription>;
async fn set_local_description(&self, desc: RTCSessionDescription) -> Result<()>;
async fn local_description(&self) -> Option<RTCSessionDescription>;
async fn current_local_description(&self) -> Option<RTCSessionDescription>;
async fn pending_local_description(&self) -> Option<RTCSessionDescription>;
async fn can_trickle_ice_candidates(&self) -> Option<bool>;
async fn set_remote_description(&self, desc: RTCSessionDescription) -> Result<()>;
async fn remote_description(&self) -> Option<RTCSessionDescription>;
async fn current_remote_description(&self) -> Option<RTCSessionDescription>;
async fn pending_remote_description(&self) -> Option<RTCSessionDescription>;
async fn add_ice_candidate(&self, candidate: RTCIceCandidateInit) -> Result<()>;
async fn restart_ice(&self) -> Result<()>;
async fn get_configuration(&self) -> RTCConfiguration;
async fn set_configuration(&self, configuration: RTCConfiguration) -> Result<()>;
async fn create_data_channel(
&self,
label: &str,
options: Option<RTCDataChannelInit>,
) -> Result<Arc<dyn DataChannel>>;
async fn get_senders(&self) -> Vec<Arc<dyn RtpSender>>;
async fn get_receivers(&self) -> Vec<Arc<dyn RtpReceiver>>;
async fn get_transceivers(&self) -> Vec<Arc<dyn RtpTransceiver>>;
async fn add_track(&self, track: Arc<dyn TrackLocal>) -> Result<Arc<dyn RtpSender>>;
async fn remove_track(&self, sender: &Arc<dyn RtpSender>) -> Result<()>;
async fn add_transceiver_from_track(
&self,
track: Arc<dyn TrackLocal>,
init: Option<RTCRtpTransceiverInit>,
) -> Result<Arc<dyn RtpTransceiver>>;
async fn add_transceiver_from_kind(
&self,
kind: RtpCodecKind,
init: Option<RTCRtpTransceiverInit>,
) -> Result<Arc<dyn RtpTransceiver>>;
async fn get_stats(&self, now: Instant, selector: StatsSelector) -> RTCStatsReport;
}
pub(crate) struct PeerConnectionImpl<I = NoopInterceptor>
where
I: Interceptor,
{
inner: Arc<PeerConnectionRef<I>>,
driver_handle: Mutex<Option<JoinHandle>>,
}
pub(crate) struct PeerConnectionRef<I = NoopInterceptor>
where
I: Interceptor,
{
pub(crate) core: Mutex<RTCPeerConnection<I>>,
pub(crate) runtime: Arc<dyn Runtime>,
pub(crate) handler: Arc<dyn PeerConnectionEventHandler>,
pub(crate) rtp_transceivers: Mutex<HashMap<RTCRtpTransceiverId, Arc<RtpTransceiverImpl<I>>>>,
pub(crate) driver_event_tx: Sender<PeerConnectionDriverEvent>,
pub(crate) data_channel_events_tx: Mutex<HashMap<RTCDataChannelId, Sender<DataChannelEvent>>>,
#[allow(clippy::type_complexity)]
pub(crate) track_remote_events_tx:
Mutex<HashMap<MediaStreamTrackId, (Sender<TrackRemoteEvent>, Arc<dyn TrackRemote>)>>,
}
impl<I> PeerConnectionImpl<I>
where
I: Interceptor,
{
async fn new<A: ToSocketAddrs>(
core: RTCPeerConnection<I>,
runtime: Arc<dyn Runtime>,
handler: Arc<dyn PeerConnectionEventHandler>,
opts: RTCIceGatherOptions,
udp_addrs: Vec<A>,
_tcp_addrs: Vec<A>,
) -> Result<Self> {
let mut local_addrs = vec![];
let mut async_udp_sockets = HashMap::new();
for addr in udp_addrs {
let socket = std::net::UdpSocket::bind(addr)?;
socket.set_nonblocking(true)?;
let local_addr = socket.local_addr()?;
let async_udp_socket = runtime.wrap_udp_socket(socket)?;
if async_udp_sockets
.insert(local_addr, async_udp_socket)
.is_none()
{
local_addrs.push(local_addr);
}
}
let (driver_event_tx, driver_event_rx) =
channel(PEER_CONNECTION_DRIVER_EVENT_CHANNEL_CAPACITY);
let peer_connection = Self {
inner: Arc::new(PeerConnectionRef {
core: Mutex::new(core),
runtime: runtime.clone(),
data_channel_events_tx: Mutex::new(HashMap::new()),
track_remote_events_tx: Mutex::new(HashMap::new()),
rtp_transceivers: Mutex::new(HashMap::new()),
handler,
driver_event_tx,
}),
driver_handle: Mutex::new(None),
};
let ice_gatherer = RTCIceGatherer::new(local_addrs, opts);
let mut driver = PeerConnectionDriver::new(
peer_connection.inner.clone(),
ice_gatherer,
async_udp_sockets,
)
.await?;
let driver_handle = runtime.spawn(Box::pin(async move {
if let Err(e) = driver.event_loop(driver_event_rx).await {
error!("I/O error: {}", e);
}
}));
*peer_connection.driver_handle.lock().await = Some(driver_handle);
Ok(peer_connection)
}
}
#[async_trait::async_trait]
impl<I> PeerConnection for PeerConnectionImpl<I>
where
I: Interceptor + 'static,
{
async fn close(&self) -> Result<()> {
{
let mut core = self.inner.core.lock().await;
core.close()?;
}
self.inner
.driver_event_tx
.send(PeerConnectionDriverEvent::Close)
.await
.map_err(|e| Error::Other(format!("{:?}", e)))?;
{
let mut driver_handle = self.driver_handle.lock().await;
if let Some(driver_handle) = driver_handle.take() {
driver_handle.abort();
}
}
Ok(())
}
async fn create_offer(
&self,
options: Option<RTCOfferOptions>,
) -> Result<RTCSessionDescription> {
let mut core = self.inner.core.lock().await;
core.create_offer(options)
}
async fn create_answer(
&self,
options: Option<RTCAnswerOptions>,
) -> Result<RTCSessionDescription> {
let mut core = self.inner.core.lock().await;
core.create_answer(options)
}
async fn set_local_description(&self, desc: RTCSessionDescription) -> Result<()> {
{
let mut core = self.inner.core.lock().await;
core.set_local_description(desc)?;
}
self.inner
.driver_event_tx
.send(PeerConnectionDriverEvent::IceGathering)
.await
.map_err(|e| Error::Other(format!("{:?}", e)))
}
async fn local_description(&self) -> Option<RTCSessionDescription> {
let core = self.inner.core.lock().await;
core.local_description()
}
async fn current_local_description(&self) -> Option<RTCSessionDescription> {
let core = self.inner.core.lock().await;
core.current_local_description()
}
async fn pending_local_description(&self) -> Option<RTCSessionDescription> {
let core = self.inner.core.lock().await;
core.pending_local_description()
}
async fn can_trickle_ice_candidates(&self) -> Option<bool> {
let core = self.inner.core.lock().await;
core.can_trickle_ice_candidates()
}
async fn set_remote_description(&self, desc: RTCSessionDescription) -> Result<()> {
{
let mut core = self.inner.core.lock().await;
core.set_remote_description(desc)?;
}
self.inner
.driver_event_tx
.send(PeerConnectionDriverEvent::WriteNotify)
.await
.map_err(|e| Error::Other(format!("{:?}", e)))
}
async fn remote_description(&self) -> Option<RTCSessionDescription> {
let core = self.inner.core.lock().await;
core.remote_description().cloned()
}
async fn current_remote_description(&self) -> Option<RTCSessionDescription> {
let core = self.inner.core.lock().await;
core.current_remote_description().cloned()
}
async fn pending_remote_description(&self) -> Option<RTCSessionDescription> {
let core = self.inner.core.lock().await;
core.pending_remote_description().cloned()
}
async fn add_ice_candidate(&self, candidate: RTCIceCandidateInit) -> Result<()> {
let mut core = self.inner.core.lock().await;
core.add_remote_candidate(candidate)?;
Ok(())
}
async fn restart_ice(&self) -> Result<()> {
{
let mut core = self.inner.core.lock().await;
core.restart_ice();
}
self.inner
.driver_event_tx
.send(PeerConnectionDriverEvent::IceGathering)
.await
.map_err(|e| Error::Other(format!("{:?}", e)))
}
async fn get_configuration(&self) -> RTCConfiguration {
let core = self.inner.core.lock().await;
core.get_configuration().clone()
}
async fn set_configuration(&self, configuration: RTCConfiguration) -> Result<()> {
let mut core = self.inner.core.lock().await;
core.set_configuration(configuration)
}
async fn create_data_channel(
&self,
label: &str,
options: Option<RTCDataChannelInit>,
) -> Result<Arc<dyn DataChannel>> {
let channel_id = {
let mut core = self.inner.core.lock().await;
let rtc_dc = core.create_data_channel(label, options)?;
rtc_dc.id()
};
let (evt_tx, evt_rx) = channel(DATA_CHANNEL_EVENT_CHANNEL_CAPACITY);
{
let mut data_channels = self.inner.data_channel_events_tx.lock().await;
data_channels.insert(channel_id, evt_tx);
}
Ok(Arc::new(DataChannelImpl::new(
channel_id,
self.inner.clone(),
evt_rx,
)))
}
async fn get_senders(&self) -> Vec<Arc<dyn RtpSender>> {
let mut rtp_senders = vec![];
for rtp_transceiver in self.get_transceivers().await {
if let Ok(sender) = rtp_transceiver.sender().await
&& let Some(rtp_sender) = sender
{
rtp_senders.push(rtp_sender);
}
}
rtp_senders
}
async fn get_receivers(&self) -> Vec<Arc<dyn RtpReceiver>> {
let mut rtp_receivers = vec![];
for rtp_transceiver in self.get_transceivers().await {
if let Ok(receiver) = rtp_transceiver.receiver().await
&& let Some(rtp_receiver) = receiver
{
rtp_receivers.push(rtp_receiver);
}
}
rtp_receivers
}
async fn get_transceivers(&self) -> Vec<Arc<dyn RtpTransceiver>> {
let current_transceiver_ids: HashSet<RTCRtpTransceiverId> = {
let core = self.inner.core.lock().await;
core.get_transceivers().collect::<HashSet<_>>()
};
let mut rtp_transceivers = self.inner.rtp_transceivers.lock().await;
rtp_transceivers.retain(|id, _| current_transceiver_ids.contains(id));
for id in current_transceiver_ids {
rtp_transceivers
.entry(id)
.or_insert_with(|| Arc::new(RtpTransceiverImpl::new(id, Arc::clone(&self.inner))));
}
rtp_transceivers
.values()
.cloned()
.map(|t| t as Arc<dyn RtpTransceiver>)
.collect()
}
async fn add_track(&self, track: Arc<dyn TrackLocal>) -> Result<Arc<dyn RtpSender>> {
let id: RTCRtpTransceiverId = {
let mut core = self.inner.core.lock().await;
core.add_track(track.track().await)?.into()
};
let mut rtp_transceivers = self.inner.rtp_transceivers.lock().await;
rtp_transceivers
.entry(id)
.or_insert_with(|| Arc::new(RtpTransceiverImpl::new(id, Arc::clone(&self.inner))));
let rtp_transceiver = rtp_transceivers
.get(&id)
.ok_or(Error::ErrRTPTransceiverNotExisted)?;
let sender: Arc<dyn RtpSender> = Arc::new(RtpSenderImpl::new(
id.into(),
Arc::clone(&self.inner),
track,
));
rtp_transceiver.set_sender(Some(Arc::clone(&sender))).await;
Ok(sender)
}
async fn remove_track(&self, sender: &Arc<dyn RtpSender>) -> Result<()> {
{
let mut core = self.inner.core.lock().await;
core.remove_track(sender.id())?;
}
let rtp_transceivers = self.inner.rtp_transceivers.lock().await;
let rtp_transceiver = rtp_transceivers
.get(&sender.id().into())
.ok_or(Error::ErrRTPTransceiverNotExisted)?;
rtp_transceiver.set_sender(None).await;
Ok(())
}
async fn add_transceiver_from_track(
&self,
track: Arc<dyn TrackLocal>,
init: Option<RTCRtpTransceiverInit>,
) -> Result<Arc<dyn RtpTransceiver>> {
let id: RTCRtpTransceiverId = {
let mut core = self.inner.core.lock().await;
core.add_transceiver_from_track(track.track().await, init)?
};
let mut rtp_transceivers = self.inner.rtp_transceivers.lock().await;
rtp_transceivers
.entry(id)
.or_insert_with(|| Arc::new(RtpTransceiverImpl::new(id, Arc::clone(&self.inner))));
let rtp_transceiver = rtp_transceivers
.get(&id)
.ok_or(Error::ErrRTPTransceiverNotExisted)?;
let sender: Arc<dyn RtpSender> = Arc::new(RtpSenderImpl::new(
id.into(),
Arc::clone(&self.inner),
track,
));
rtp_transceiver.set_sender(Some(sender)).await;
Ok(rtp_transceiver.clone() as Arc<dyn RtpTransceiver>)
}
async fn add_transceiver_from_kind(
&self,
kind: RtpCodecKind,
init: Option<RTCRtpTransceiverInit>,
) -> Result<Arc<dyn RtpTransceiver>> {
let (id, track) = {
let mut core = self.inner.core.lock().await;
let id = core.add_transceiver_from_kind(kind, init)?;
(
id,
core.rtp_sender(id.into())
.map(|sender| sender.track().clone()),
)
};
let mut rtp_transceivers = self.inner.rtp_transceivers.lock().await;
rtp_transceivers
.entry(id)
.or_insert_with(|| Arc::new(RtpTransceiverImpl::new(id, Arc::clone(&self.inner))));
let rtp_transceiver = rtp_transceivers
.get(&id)
.ok_or(Error::ErrRTPTransceiverNotExisted)?;
if let Some(track) = track {
let sender: Arc<dyn RtpSender> = Arc::new(RtpSenderImpl::new(
id.into(),
Arc::clone(&self.inner),
Arc::new(TrackLocalStaticRTP::new(track)),
));
rtp_transceiver.set_sender(Some(sender)).await;
}
Ok(rtp_transceiver.clone() as Arc<dyn RtpTransceiver>)
}
async fn get_stats(&self, now: Instant, selector: StatsSelector) -> RTCStatsReport {
let mut core = self.inner.core.lock().await;
core.get_stats(now, selector)
}
}