use rtc::shared::FourTuple;
use std::io;
use std::net::SocketAddr;
pub(crate) mod stun_gatherer;
pub(crate) mod tcp_transport;
pub(crate) mod turn_relayer;
pub(crate) const UDP_RECV_BUF_LEN: usize = 2000;
pub(crate) const MAX_GRO_SEGMENTS: usize = 64;
pub(crate) const MAX_GSO_SEGMENTS: usize = 64;
pub(crate) const MAX_GSO_BATCH_BYTES: usize = 65535;
pub(crate) const MIN_GSO_RUN: usize = 16;
pub(crate) const GRO_RECV_SEGMENT_LEN: usize = 1500;
pub(crate) fn gro_recv_buf_len(max_gro: usize) -> usize {
if max_gro > 1 {
max_gro.min(MAX_GRO_SEGMENTS) * GRO_RECV_SEGMENT_LEN
} else {
UDP_RECV_BUF_LEN
}
}
pub(crate) enum SocketRecvResult {
Packet {
n: usize,
stride: usize,
local_addr: SocketAddr,
peer_addr: SocketAddr,
idx: usize,
buf: Vec<u8>,
},
Error {
err: io::Error,
local_addr: SocketAddr,
idx: usize,
buf: Vec<u8>,
},
}
pub(crate) enum TcpReadResult {
Packet {
four_tuple: FourTuple,
n: usize,
buf: Vec<u8>,
},
Error {
four_tuple: FourTuple,
err: io::Error,
buf: Vec<u8>,
},
}
pub(crate) fn is_retryable_socket_recv_error(err: &io::Error) -> bool {
matches!(
err.kind(),
io::ErrorKind::Interrupted
| io::ErrorKind::WouldBlock
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::ConnectionReset
| io::ErrorKind::TimedOut
)
}
#[cfg(test)]
mod gro_buf_tests {
use super::{GRO_RECV_SEGMENT_LEN, MAX_GRO_SEGMENTS, UDP_RECV_BUF_LEN, gro_recv_buf_len};
#[test]
fn gro_recv_buf_len_sizes_for_capacity_and_falls_back_without_gro() {
assert_eq!(gro_recv_buf_len(64), 64 * GRO_RECV_SEGMENT_LEN);
assert_eq!(gro_recv_buf_len(8), 8 * GRO_RECV_SEGMENT_LEN);
assert_eq!(
gro_recv_buf_len(1000),
MAX_GRO_SEGMENTS * GRO_RECV_SEGMENT_LEN
);
assert_eq!(gro_recv_buf_len(1), UDP_RECV_BUF_LEN);
}
}
use crate::error::{Error, Result};
use crate::peer_connection::PeerConnectionRef;
use rtc::peer_connection::RTCPeerConnection;
use rtc::peer_connection::state::RTCIceGatheringState;
use rtc::peer_connection::transport::{
RTCDtlsTransport as CoreDtlsTransport, RTCDtlsTransportState, RTCIceCandidate,
RTCIceCandidatePair, RTCIceComponent, RTCIceParameters, RTCIceRole, RTCIceTransportState,
RTCSctpTransportState, RTCTransportId,
};
use rtc::rtp_transceiver::{RTCRtpReceiverId, RTCRtpSenderId};
use std::sync::Arc;
#[async_trait::async_trait]
pub trait SctpTransport: crate::sealed::Sealed + Send + Sync + 'static {
fn id(&self) -> RTCTransportId;
fn transport(&self) -> Arc<dyn DtlsTransport>;
async fn state(&self) -> Result<RTCSctpTransportState>;
async fn max_message_size(&self) -> Result<u32>;
async fn max_channels(&self) -> Result<Option<u16>>;
}
#[async_trait::async_trait]
pub trait DtlsTransport: crate::sealed::Sealed + Send + Sync + 'static {
fn id(&self) -> RTCTransportId;
fn ice_transport(&self) -> Arc<dyn IceTransport>;
async fn state(&self) -> Result<RTCDtlsTransportState>;
async fn get_remote_certificates(&self) -> Result<Vec<Vec<u8>>>;
}
#[async_trait::async_trait]
pub trait IceTransport: crate::sealed::Sealed + Send + Sync + 'static {
fn id(&self) -> RTCTransportId;
fn component(&self) -> RTCIceComponent;
async fn role(&self) -> Result<RTCIceRole>;
async fn state(&self) -> Result<RTCIceTransportState>;
async fn gathering_state(&self) -> Result<RTCIceGatheringState>;
async fn get_local_candidates(&self) -> Result<Vec<RTCIceCandidate>>;
async fn get_remote_candidates(&self) -> Result<Vec<RTCIceCandidate>>;
async fn get_selected_candidate_pair(&self) -> Result<Option<RTCIceCandidatePair>>;
async fn get_local_parameters(&self) -> Result<Option<RTCIceParameters>>;
async fn get_remote_parameters(&self) -> Result<Option<RTCIceParameters>>;
}
#[derive(Clone, Copy, Debug)]
pub(crate) enum DtlsRoute {
Sctp,
Sender(RTCRtpSenderId),
Receiver(RTCRtpReceiverId),
}
impl DtlsRoute {
fn with_dtls<T>(
self,
peer_connection: &mut RTCPeerConnection,
f: impl FnOnce(CoreDtlsTransport<'_>) -> T,
) -> Option<T> {
match self {
DtlsRoute::Sctp => peer_connection.sctp().map(|sctp| f(sctp.transport())),
DtlsRoute::Sender(id) => match peer_connection.rtp_sender(id) {
Some(sender) => sender.transport().map(f),
None => None,
},
DtlsRoute::Receiver(id) => match peer_connection.rtp_receiver(id) {
Some(receiver) => receiver.transport().map(f),
None => None,
},
}
}
}
pub(crate) struct SctpTransportImpl {
id: RTCTransportId,
dtls_id: RTCTransportId,
ice_id: RTCTransportId,
inner: Arc<PeerConnectionRef>,
}
impl SctpTransportImpl {
pub(crate) fn new(
id: RTCTransportId,
dtls_id: RTCTransportId,
ice_id: RTCTransportId,
inner: Arc<PeerConnectionRef>,
) -> Self {
Self {
id,
dtls_id,
ice_id,
inner,
}
}
}
impl crate::sealed::Sealed for SctpTransportImpl {}
#[async_trait::async_trait]
impl SctpTransport for SctpTransportImpl {
fn id(&self) -> RTCTransportId {
self.id
}
fn transport(&self) -> Arc<dyn DtlsTransport> {
Arc::new(DtlsTransportImpl::new(
self.dtls_id,
self.ice_id,
DtlsRoute::Sctp,
Arc::clone(&self.inner),
))
}
async fn state(&self) -> Result<RTCSctpTransportState> {
let peer_connection = self.inner.core.lock().await;
Ok(peer_connection
.sctp()
.ok_or(Error::ErrSCTPTransportNotExisted)?
.state())
}
async fn max_message_size(&self) -> Result<u32> {
let peer_connection = self.inner.core.lock().await;
peer_connection
.sctp()
.ok_or(Error::ErrSCTPTransportNotExisted)?
.max_message_size()
.ok_or(Error::ErrSCTPTransportNotExisted)
}
async fn max_channels(&self) -> Result<Option<u16>> {
let peer_connection = self.inner.core.lock().await;
Ok(peer_connection
.sctp()
.ok_or(Error::ErrSCTPTransportNotExisted)?
.max_channels())
}
}
pub(crate) struct DtlsTransportImpl {
id: RTCTransportId,
ice_id: RTCTransportId,
route: DtlsRoute,
inner: Arc<PeerConnectionRef>,
}
impl DtlsTransportImpl {
pub(crate) fn new(
id: RTCTransportId,
ice_id: RTCTransportId,
route: DtlsRoute,
inner: Arc<PeerConnectionRef>,
) -> Self {
Self {
id,
ice_id,
route,
inner,
}
}
}
impl crate::sealed::Sealed for DtlsTransportImpl {}
#[async_trait::async_trait]
impl DtlsTransport for DtlsTransportImpl {
fn id(&self) -> RTCTransportId {
self.id
}
fn ice_transport(&self) -> Arc<dyn IceTransport> {
Arc::new(IceTransportImpl::new(
self.ice_id,
self.route,
Arc::clone(&self.inner),
))
}
async fn state(&self) -> Result<RTCDtlsTransportState> {
let mut peer_connection = self.inner.core.lock().await;
self.route
.with_dtls(&mut peer_connection, |dtls| dtls.state())
.ok_or(Error::ErrDTLSTransportNotExisted)
}
async fn get_remote_certificates(&self) -> Result<Vec<Vec<u8>>> {
let mut peer_connection = self.inner.core.lock().await;
self.route
.with_dtls(&mut peer_connection, |dtls| {
dtls.get_remote_certificates().to_vec()
})
.ok_or(Error::ErrDTLSTransportNotExisted)
}
}
pub(crate) struct IceTransportImpl {
id: RTCTransportId,
route: DtlsRoute,
inner: Arc<PeerConnectionRef>,
}
impl IceTransportImpl {
pub(crate) fn new(id: RTCTransportId, route: DtlsRoute, inner: Arc<PeerConnectionRef>) -> Self {
Self { id, route, inner }
}
}
impl crate::sealed::Sealed for IceTransportImpl {}
macro_rules! read_ice {
($self:ident, |$ice:ident| $body:expr) => {{
let mut peer_connection = $self.inner.core.lock().await;
$self
.route
.with_dtls(&mut peer_connection, |dtls| {
let $ice = dtls.ice_transport();
$body
})
.ok_or(Error::ErrDTLSTransportNotExisted)
}};
}
#[async_trait::async_trait]
impl IceTransport for IceTransportImpl {
fn id(&self) -> RTCTransportId {
self.id
}
fn component(&self) -> RTCIceComponent {
RTCIceComponent::Rtp
}
async fn role(&self) -> Result<RTCIceRole> {
read_ice!(self, |ice| ice.role())
}
async fn state(&self) -> Result<RTCIceTransportState> {
read_ice!(self, |ice| ice.state())
}
async fn gathering_state(&self) -> Result<RTCIceGatheringState> {
read_ice!(self, |ice| ice.gathering_state())
}
async fn get_local_candidates(&self) -> Result<Vec<RTCIceCandidate>> {
read_ice!(self, |ice| ice.get_local_candidates())
}
async fn get_remote_candidates(&self) -> Result<Vec<RTCIceCandidate>> {
read_ice!(self, |ice| ice.get_remote_candidates())
}
async fn get_selected_candidate_pair(&self) -> Result<Option<RTCIceCandidatePair>> {
read_ice!(self, |ice| ice.get_selected_candidate_pair())
}
async fn get_local_parameters(&self) -> Result<Option<RTCIceParameters>> {
read_ice!(self, |ice| ice.get_local_parameters())
}
async fn get_remote_parameters(&self) -> Result<Option<RTCIceParameters>> {
read_ice!(self, |ice| ice.get_remote_parameters())
}
}