diff --git a/ice/src/tcp_type/mod.rs b/ice/src/tcp_type/mod.rs index 11f7bdbcb..72b69b96c 100644 --- a/ice/src/tcp_type/mod.rs +++ b/ice/src/tcp_type/mod.rs @@ -4,7 +4,7 @@ mod tcp_type_test; use std::fmt; // TCPType is the type of ICE TCP candidate as described in -// ttps://tools.ietf.org/html/rfc6544#section-4.5 +// https://tools.ietf.org/html/rfc6544#section-4.5 #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum TcpType { /// The default value. For example UDP candidates do not need this field. diff --git a/ice/src/udp_mux/mod.rs b/ice/src/udp_mux/mod.rs index b2ef39cdd..56b69e08f 100644 --- a/ice/src/udp_mux/mod.rs +++ b/ice/src/udp_mux/mod.rs @@ -137,7 +137,7 @@ impl UDPMuxDefault { let s = match String::from_utf8(attr.value) { // Per the RFC this shouldn't happen - // https://datatracker.ietf.org/doc/html/rfc5389#section-15.3 + // https://tools.ietf.org/html/rfc5389#section-15.3 Err(err) => { log::warn!( "Failed to decode USERNAME from STUN message as UTF-8: {}", diff --git a/interceptor/src/stats/interceptor.rs b/interceptor/src/stats/interceptor.rs index 30aab7197..daa1fa831 100644 --- a/interceptor/src/stats/interceptor.rs +++ b/interceptor/src/stats/interceptor.rs @@ -787,7 +787,7 @@ impl RTPWriter for RTPWriteRecorder { } /// Calculate the round trip time for a given peer as described in -/// [RFC3550 6.4.1](https://datatracker.ietf.org/doc/html/rfc3550#section-6.4.1). +/// [RFC3550 6.4.1](https://tools.ietf.org/html/rfc3550#section-6.4.1). /// /// ## Params /// diff --git a/interceptor/src/stats/mod.rs b/interceptor/src/stats/mod.rs index 2f1bb0074..ccc9e0002 100644 --- a/interceptor/src/stats/mod.rs +++ b/interceptor/src/stats/mod.rs @@ -362,7 +362,7 @@ mod outbound { remote_round_trip_time_measurements: u64, /// The fraction of packets lost reported for this stream. - /// Calculated as defined in [RFC3550](https://www.rfc-editor.org/rfc/rfc3550) section 6.4.1 and Appendix A.3. + /// Calculated as defined in [RFC3550](https://tools.ietf.org/html/rfc3550) section 6.4.1 and Appendix A.3. remote_fraction_lost: Option, } diff --git a/interceptor/src/twcc/mod.rs b/interceptor/src/twcc/mod.rs index 463200079..c2f9fef1b 100644 --- a/interceptor/src/twcc/mod.rs +++ b/interceptor/src/twcc/mod.rs @@ -19,7 +19,7 @@ struct PktInfo { /// Recorder records incoming RTP packets and their delays and creates /// transport wide congestion control feedback reports as specified in -/// https://datatracker.ietf.org/doc/html/draft-holmer-rmcat-transport-wide-cc-extensions-01 +/// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01 #[derive(Default, Debug, PartialEq, Clone)] pub struct Recorder { received_packets: Vec, diff --git a/interceptor/src/twcc/receiver/mod.rs b/interceptor/src/twcc/receiver/mod.rs index 7caf4a140..74d12c3b3 100644 --- a/interceptor/src/twcc/receiver/mod.rs +++ b/interceptor/src/twcc/receiver/mod.rs @@ -69,7 +69,7 @@ struct ReceiverInternal { } /// Receiver sends transport wide congestion control reports as specified in: -/// https://datatracker.ietf.org/doc/html/draft-holmer-rmcat-transport-wide-cc-extensions-01 +/// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01 pub struct Receiver { internal: Arc, diff --git a/rtp/src/codecs/h265/mod.rs b/rtp/src/codecs/h265/mod.rs index a06c8b512..4b10e0168 100644 --- a/rtp/src/codecs/h265/mod.rs +++ b/rtp/src/codecs/h265/mod.rs @@ -11,15 +11,15 @@ mod h265_test; /// const H265NALU_HEADER_SIZE: usize = 2; -/// https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 +/// https://tools.ietf.org/html/rfc7798#section-4.4.2 const H265NALU_AGGREGATION_PACKET_TYPE: u8 = 48; -/// https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.3 +/// https://tools.ietf.org/html/rfc7798#section-4.4.3 const H265NALU_FRAGMENTATION_UNIT_TYPE: u8 = 49; -/// https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.4 +/// https://tools.ietf.org/html/rfc7798#section-4.4.4 const H265NALU_PACI_PACKET_TYPE: u8 = 50; /// H265NALUHeader is a H265 NAL Unit Header -/// https://datatracker.ietf.org/doc/html/rfc7798#section-1.1.4 +/// https://tools.ietf.org/html/rfc7798#section-1.1.4 /// +---------------+---------------+ /// |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -97,7 +97,7 @@ impl H265NALUHeader { /// | :...OPTIONAL RTP padding | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// -/// Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.1 +/// Reference: https://tools.ietf.org/html/rfc7798#section-4.4.1 #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct H265SingleNALUnitPacket { /// payload_header is the header of the H265 packet. @@ -186,7 +186,7 @@ impl H265SingleNALUnitPacket { /// | : /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// -/// Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 +/// Reference: https://tools.ietf.org/html/rfc7798#section-4.4.2 #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct H265AggregationUnitFirst { donl: Option, @@ -226,7 +226,7 @@ impl H265AggregationUnitFirst { /// | : /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// -/// Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 +/// Reference: https://tools.ietf.org/html/rfc7798#section-4.4.2 #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct H265AggregationUnit { dond: Option, @@ -266,7 +266,7 @@ impl H265AggregationUnit { /// | :...OPTIONAL RTP padding | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// -/// Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 +/// Reference: https://tools.ietf.org/html/rfc7798#section-4.4.2 #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct H265AggregationPacket { first_unit: Option, @@ -427,7 +427,7 @@ impl H265FragmentationUnitHeader { /// | :...OPTIONAL RTP padding | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// -/// Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.3 +/// Reference: https://tools.ietf.org/html/rfc7798#section-4.4.3 #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct H265FragmentationUnitPacket { /// payload_header is the header of the H265 packet. @@ -526,7 +526,7 @@ impl H265FragmentationUnitPacket { /// | :...OPTIONAL RTP padding | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// -/// Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.4 +/// Reference: https://tools.ietf.org/html/rfc7798#section-4.4.4 #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct H265PACIPacket { /// payload_header is the header of the H265 packet. @@ -655,7 +655,7 @@ impl H265PACIPacket { /// /// H265TSCI is a Temporal Scalability Control Information header extension. -/// Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.5 +/// Reference: https://tools.ietf.org/html/rfc7798#section-4.5 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] pub struct H265TSCI(pub u32); diff --git a/sctp/src/association/association_internal.rs b/sctp/src/association/association_internal.rs index 3caf030b1..afa02991f 100644 --- a/sctp/src/association/association_internal.rs +++ b/sctp/src/association/association_internal.rs @@ -665,7 +665,7 @@ impl AssociationInternal { ..Default::default() }; - // According to RFC https://datatracker.ietf.org/doc/html/rfc4960#section-3.2.2 + // According to RFC https://tools.ietf.org/html/rfc4960#section-3.2.2 // We report unknown parameters with a paramtype with bit 14 set as unrecognized let unrecognized_params_from_init = i .params @@ -2174,7 +2174,7 @@ impl AssociationInternal { self.handle_shutdown_complete(c).await? } else { /* - https://datatracker.ietf.org/doc/html/rfc4960#section-3 + https://tools.ietf.org/html/rfc4960#section-3 00 - Stop processing this SCTP packet and discard it, do not process any further chunks within it. diff --git a/sctp/src/param/mod.rs b/sctp/src/param/mod.rs index 49ca3c962..fde16932a 100644 --- a/sctp/src/param/mod.rs +++ b/sctp/src/param/mod.rs @@ -75,7 +75,7 @@ pub(crate) fn build_param(raw_param: &Bytes) -> Result Ok(Box::new(ParamOutgoingResetRequest::unmarshal(raw_param)?)), ParamType::ReconfigResp => Ok(Box::new(ParamReconfigResponse::unmarshal(raw_param)?)), _ => { - // According to RFC https://datatracker.ietf.org/doc/html/rfc4960#section-3.2.1 + // According to RFC https://tools.ietf.org/html/rfc4960#section-3.2.1 let stop_processing = ((raw_type >> 15) & 0x01) == 0; if stop_processing { Err(Error::ErrParamTypeUnhandled { typ: raw_type }) diff --git a/webrtc/src/ice_transport/ice_connection_state.rs b/webrtc/src/ice_transport/ice_connection_state.rs index d019854ae..b0c5a05a3 100644 --- a/webrtc/src/ice_transport/ice_connection_state.rs +++ b/webrtc/src/ice_transport/ice_connection_state.rs @@ -1,44 +1,61 @@ use std::fmt; -/// RTCIceConnectionState indicates signaling state of the ICE Connection. +/// Indicates the signaling state of the ICE Connection. #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] pub enum RTCIceConnectionState { #[default] Unspecified, - /// ICEConnectionStateNew indicates that any of the ICETransports are - /// in the "new" state and none of them are in the "checking", "disconnected" - /// or "failed" state, or all ICETransports are in the "closed" state, or - /// there are no transports. - New, + /// Indicates that the [`RTCPeerConnection`] is closed + /// + /// [`RTCPeerConnection`]: crate::peer_connection::RTCPeerConnection + Closed, - /// ICEConnectionStateChecking indicates that any of the ICETransports - /// are in the "checking" state and none of them are in the "disconnected" - /// or "failed" state. - Checking, + /// Indicates all of the following: + /// - the previous state does not apply + /// - any of the [`RTCIceTransport`]s are in the `failed` state + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + Failed, - /// ICEConnectionStateConnected indicates that all ICETransports are - /// in the "connected", "completed" or "closed" state and at least one of - /// them is in the "connected" state. - Connected, + /// Indicates all of the following: + /// - none of the previous states apply + /// - any of the [`RTCIceTransport`]s are in the `disconnected` state + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + Disconnected, - /// ICEConnectionStateCompleted indicates that all ICETransports are - /// in the "completed" or "closed" state and at least one of them is in the - /// "completed" state. - Completed, + /// Indicates all of the following: + /// - none of the previous states apply + /// - all of the [`RTCIceTransport`]s are in the `new` or + /// `closed` state, or + /// - there are no transports + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + New, - /// ICEConnectionStateDisconnected indicates that any of the - /// ICETransports are in the "disconnected" state and none of them are - /// in the "failed" state. - Disconnected, + /// Indicates all of the following: + /// - none of the previous states apply + /// - any of the [`RTCIceTransport`]s are in the `new` or `checking` state + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + Checking, - /// ICEConnectionStateFailed indicates that any of the ICETransports - /// are in the "failed" state. - Failed, + /// Indicates all of the following: + /// - none of the previous states apply + /// - all of the [`RTCIceTransport`]s are in the `completed` or + /// `closed` state + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + Completed, - /// ICEConnectionStateClosed indicates that the PeerConnection's - /// isClosed is true. - Closed, + /// Indicates all of the following: + /// - none of the previous states apply + /// - all of the [`RTCIceTransport`]s are in the `connected`, `completed`, or + /// `closed` state + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + Connected, } const ICE_CONNECTION_STATE_NEW_STR: &str = "new"; @@ -68,13 +85,13 @@ impl From<&str> for RTCIceConnectionState { impl From for RTCIceConnectionState { fn from(v: u8) -> Self { match v { - 1 => RTCIceConnectionState::New, - 2 => RTCIceConnectionState::Checking, - 3 => RTCIceConnectionState::Connected, - 4 => RTCIceConnectionState::Completed, - 5 => RTCIceConnectionState::Disconnected, - 6 => RTCIceConnectionState::Failed, - 7 => RTCIceConnectionState::Closed, + 1 => RTCIceConnectionState::Closed, + 2 => RTCIceConnectionState::Failed, + 3 => RTCIceConnectionState::Disconnected, + 4 => RTCIceConnectionState::New, + 5 => RTCIceConnectionState::Checking, + 6 => RTCIceConnectionState::Completed, + 7 => RTCIceConnectionState::Connected, _ => RTCIceConnectionState::Unspecified, } } diff --git a/webrtc/src/ice_transport/ice_gathering_state.rs b/webrtc/src/ice_transport/ice_gathering_state.rs index fa043312d..ca44a77f9 100644 --- a/webrtc/src/ice_transport/ice_gathering_state.rs +++ b/webrtc/src/ice_transport/ice_gathering_state.rs @@ -1,22 +1,28 @@ use std::fmt; -/// ICEGatheringState describes the state of the candidate gathering process. +/// Describes the state of the ICE candidate gathering process. #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] pub enum RTCIceGatheringState { #[default] Unspecified, - /// ICEGatheringStateNew indicates that any of the ICETransports are - /// in the "new" gathering state and none of the transports are in the - /// "gathering" state, or there are no transports. + /// Any of the [`RTCIceTransport`]s are + /// in the `new` gathering state and none of the transports are in the + /// `gathering` state, or there are no transports. + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport New, - /// ICEGatheringStateGathering indicates that any of the ICETransports - /// are in the "gathering" state. + /// Any of the [`RTCIceTransport`]s + /// are in the `gathering` state. + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport Gathering, - /// ICEGatheringStateComplete indicates that at least one ICETransport - /// exists, and all ICETransports are in the "completed" gathering state. + /// At least one [`RTCIceTransport`] + /// exists, and all [`RTCIceTransport`]s are in the `complete` gathering state. + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport Complete, } diff --git a/webrtc/src/ice_transport/ice_server.rs b/webrtc/src/ice_transport/ice_server.rs index 3cfc66f56..27bc5cb07 100644 --- a/webrtc/src/ice_transport/ice_server.rs +++ b/webrtc/src/ice_transport/ice_server.rs @@ -3,13 +3,35 @@ use serde::{Deserialize, Serialize}; use crate::error::{Error, Result}; use crate::ice_transport::ice_credential_type::RTCIceCredentialType; -/// ICEServer describes a single STUN and TURN server that can be used by -/// the ICEAgent to establish a connection with a peer. +/// Describes a single STUN or TURN server that can be used by +/// the ICE Agent to establish a connection with a peer. #[derive(Default, Debug, Clone, Serialize, Deserialize, Hash)] pub struct RTCIceServer { + /// A sequence of [STUN](https://tools.ietf.org/html/rfc5389) + /// or [TURN](https://tools.ietf.org/html/rfc5928) URIs to be used by + /// the ICE Agent to establish a connection with a peer. + /// + /// STUN URIs (defined in [RFC7064](https://tools.ietf.org/html/rfc7064)) + /// allow for the discovery of server-reflexive candidates. + /// + /// TURN URIs (defined in [RFC7065](https://tools.ietf.org/html/rfc7065)) + /// allow for the discovery of relayed candidates. pub urls: Vec, + + /// If this [`RTCIceServer`] object represents a TURN server, then this attribute + /// specifies the username to use during the authentication process with the + /// TURN server. pub username: String, + + /// If this [`RTCIceServer`] object represents a TURN server, then this attribute + /// specifies the credential to use during the authentication process with the + /// TURN server. It represents a long-term authentication password, as described + /// in [RFC5389](https://tools.ietf.org/html/rfc5389). pub credential: String, + + /// **NOT IN SPEC:** If this [`RTCIceServer`] object represents a TURN server, + /// then this attribute indicates the type of credential to use to connect + /// to the TURN server. pub credential_type: RTCIceCredentialType, } diff --git a/webrtc/src/lib.rs b/webrtc/src/lib.rs index 8eaeff247..51c403e72 100644 --- a/webrtc/src/lib.rs +++ b/webrtc/src/lib.rs @@ -1,6 +1,191 @@ #![warn(rust_2018_idioms)] #![allow(dead_code)] +//! # WebRTC Crate Overview +//! +//! The `webrtc` crate provides Rust-based bindings and high-level abstractions +//! for WebRTC, based on the [W3C specification](https://www.w3.org/TR/webrtc/). +//! Included is a set of communication protocols and APIs for building real-time +//! communication (RTC) applications on top of the WebRTC standard. +//! +//! If you would like to learn more about WebRTC in general, the +//! [WebRTC for the Curious](https://webrtcforthecurious.com/) book is a free +//! resource that provides a great introduction to the topic. +//! +//! # Features +//! +//! - Connections to remote peers using NAT-traversal technologies (STUN, TURN, and ICE) +//! - Streaming of audio and video media via RTP and RTCP +//! - Data channels for high performance, bi-directional communication +//! - Secured communications via DTLS and SRTP +//! - Multi-homing and congestion control using SCTP +//! - Support for Multicast DNS (mDNS) +//! - Interceptors for RTP, RTCP, and DataChannel packets +//! +//! # Key Concepts +//! +//! The WebRTC API, as defined by the W3C specification, is composed of a number of +//! constructs and interfaces that provide a rich set of functionality, including +//! (but not limited to): +//! - connection establishment +//! - media streaming +//! - data transfer +//! - error handling +//! - congestion control +//! +//! The following section provides a brief overview of the key concepts and constructs +//! that are used throughout the WebRTC API. +//! +//! ### Configuration +//! +//! The [`RTCConfiguration`] struct defines the set of parameters that are used to configure +//! how peer-to-peer communication via [`RTCPeerConnection`] is established or re-established. +//! This includes the set of ICE servers to use, the ICE transport policy, the bundle policy, +//! the RTCP mux policy, the peer identity, and the set of certificates to use. +//! +//! Configurations may be reused across multiple [`RTCPeerConnection`]s, and are treated as read-only +//! once constructed. +//! +//! ### Peer Connections +//! +//! The [`RTCPeerConnection`] is the primary entry point to the WebRTC API. It represents an +//! individual connection between a local device and a remote peer. +//! +//! #### State Machine +//! +//! Each [`RTCPeerConnection`] tracks four distinct states as part of its state machine: +//! +//! | State Machine | Getter Method | Event Handler Method | Enum | +//! | ------------- | ------------- | -------------------- | ---- | +//! | Signaling state | [`signaling_state()`](crate::peer_connection::RTCPeerConnection::signaling_state) | [`on_signaling_state_change()`](crate::peer_connection::RTCPeerConnection::on_signaling_state_change) | [`RTCSignalingState`](crate::peer_connection::signaling_state::RTCSignalingState) | +//! | ICE connection state | [`ice_connection_state()`](crate::peer_connection::RTCPeerConnection::ice_connection_state) | [`on_ice_connection_state_change()`](crate::peer_connection::RTCPeerConnection::on_ice_connection_state_change) | [`RTCIceConnectionState`](crate::ice_transport::ice_connection_state::RTCIceConnectionState) | +//! | ICE gathering state | [`ice_gathering_state()`](crate::peer_connection::RTCPeerConnection::ice_gathering_state) | [`on_ice_gathering_state_change()`](crate::peer_connection::RTCPeerConnection::on_ice_gathering_state_change) | [`RTCIceGatheringState`](crate::ice_transport::ice_gathering_state::RTCIceGatheringState) | +//! | Peer connection state | [`connection_state()`](crate::peer_connection::RTCPeerConnection::connection_state) !! | [`on_peer_connection_state_change()`](crate::peer_connection::RTCPeerConnection::on_peer_connection_state_change) | [`RTCPeerConnectionState`](crate::peer_connection::peer_connection_state::RTCPeerConnectionState) | +//! +//! You can define event handlers for each of these states using the corresponding `on_*` methods, +//! passing a FnMut closure that accepts the corresponding enum type and returns a +//! `Pin + Send + 'static>` future to be awaited. +//! +//! ### Event Handling +//! +//! For clarity, the event handler methods run synchronously and accept a (synchronous) closure +//! that returns a future. Any async work that you need to do as part of an event handler should +//! be placed in the future that is returned by the closure, as the returned future will be +//! immediately awaited. +//! +//! In fact, all of the event handler methods within this crate are structured in this way. +//! While it may feel odd to be forced into returning a future from a synchronous method, +//! it allows for a mix of synchronous and asynchronous work to be done within the handler, +//! depending on your specific use case. +//! +//! **This will be a common source of confusion for new users of the crate.** +//! +//! ### Session Descriptions +//! +//! In the WebRTC protocol, session descriptions serve as the mechanism for exchanging +//! information about media capabilities, network addresses, and other metadata between +//! peers. Session descriptions are represented by the [`RTCSessionDescription`] struct. +//! +//! Session descriptions are exchanged via an offer/answer model, where one peer sends +//! an offer to the other peer, and the other peer responds with an answer. Offers and +//! answers are represented by the [`RTCOfferOptions`] and [`RTCAnswerOptions`] structs, +//! respectively. +//! +//! On the wire, session descriptions are encoded as SDP +//! ([Session Description Protocol](https://en.wikipedia.org/wiki/Session_Description_Protocol)) +//! documents. +//! +//! ### Signaling +//! +//! In order to establish a connection, both peers must exchange their session descriptions +//! with each other. The process of exchanging of session descriptions between peers is +//! more commonly referred to as the signaling process. +//! +//! At a high level, the signaling process looks something like this: +//! +//! | Step # | Peer | Action | Method | +//! | :----: | :--: |--------|--------| +//! | 1 | Peer A | Creates an offer | [`create_offer()`](crate::peer_connection::RTCPeerConnection::create_offer) | +//! | 2 | Peer A | Sets the offer as the local description | [`set_local_description()`](crate::peer_connection::RTCPeerConnection::set_local_description) | +//! | 3 | Peer A | Sends the offer to Peer B via the signaling channel | | +//! | 4 | Peer B | Receives the offer from the signaling channel | | +//! | 5 | Peer B | Sets the received offer as the remote description | [`set_remote_description()`](crate::peer_connection::RTCPeerConnection::set_remote_description) | +//! | 6 | Peer B | Creates an answer | [`create_answer()`](crate::peer_connection::RTCPeerConnection::create_answer) | +//! | 7 | Peer B | Sets the answer as the local description | [`set_local_description()`](crate::peer_connection::RTCPeerConnection::set_local_description) | +//! | 8 | Peer B | Sends the answer to Peer A via the signaling channel | | +//! | 9 | Peer A | Receives the answer from the signaling channel | | +//! | 10 | Peer A | Sets the received answer as the remote description | [`set_remote_description()`](crate::peer_connection::RTCPeerConnection::set_remote_description) | +//! | 11 | Both | Are now connected | | +//! +//! #### No Automatic Signaling in WebRTC +//! +//! **In the WebRTC protocol, the signaling process does not happen automatically.** +//! +//! Signaling is outside the scope of the WebRTC specification, and is left up to the +//! application to implement. In other words, you will have to provide your own signaling +//! implementation. There is generally no one-size-fits-all solution for signaling, as +//! it is highly dependent on the specific use case (which may need to consider things +//! such as user authentication, security, encryption, etc.). +//! +//! Common signaling methods include (but may not be limited to): +//! - WebSockets +//! - HTTPS (e.g. using a REST API) +//! - SIP (Session Initiation Protocol) +//! - XMPP (Extensible Messaging and Presence Protocol) +//! +//! As signaling is an application-specific concern, this crate does not provide any +//! built-in signaling functionality or guidance on how to implement. +//! +//! ### ICE Agent +//! +//! The [`Agent`](ice::agent::Agent) struct implements the ICE ([Interactive Connectivity Establishment](https://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment)) +//! protocol, which is used to gather local ICE candidates, as well as manage the state of the +//! ICE transport for a given peer connection. +//! +//! ICE agent's configuration parameters are defined by the [`RTCConfiguration`] struct. +//! +//! Certain [`RTCPeerConnection`] methods interact with the ICE agent, including: +//! +//! - [`add_ice_candidate()`](crate::peer_connection::RTCPeerConnection::add_ice_candidate) +//! - [`set_local_description()`](crate::peer_connection::RTCPeerConnection::set_local_description) +//! - [`set_remote_description()`](crate::peer_connection::RTCPeerConnection::set_remote_description) +//! - [`close()`](crate::peer_connection::RTCPeerConnection::close) +//! +//! These interactions are described in [RFC8829](https://tools.ietf.org/html/rfc8829). The ICE +//! agency also provides indications when the state of an ICE transport changes via the event +//! handler methods that are available within [`RTCPeerConnection`]. +//! +//! ### MediaStream +//! +//! ### DataChannel +//! +//! ### RTCIceCandidate +//! +//! ### RTCSessionDescription +//! +//! # Examples +//! +//! The `examples/` directory contains a range of examples, from basic peer connections to +//! advanced data channel usage. +//! +//! # Compatibility +//! +//! This crate aims to stay up-to-date with the latest W3C WebRTC specification. However, +//! as WebRTC is a rapidly evolving standard, there might be minor discrepancies. Always +//! refer to the official W3C WebRTC specification for authoritative information. +//! +//! # License +//! +//! This project is licensed under either of the following, at your option: +//! - [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) +//! - [MIT License](https://opensource.org/license/mit/) +//! +//! [`RTCConfiguration`]: crate::peer_connection::configuration::RTCConfiguration +//! [`RTCPeerConnection`]: crate::peer_connection::RTCPeerConnection +//! [`RTCSessionDescription`]: crate::peer_connection::sdp::session_description::RTCSessionDescription +//! [`RTCOfferOptions`]: crate::peer_connection::offer_answer_options::RTCOfferOptions +//! [`RTCAnswerOptions`]: crate::peer_connection::offer_answer_options::RTCAnswerOptions + // re-export sub-crates pub use {data, dtls, ice, interceptor, mdns, media, rtcp, rtp, sctp, sdp, srtp, stun, turn, util}; diff --git a/webrtc/src/peer_connection/configuration.rs b/webrtc/src/peer_connection/configuration.rs index f5a723f65..acc17f641 100644 --- a/webrtc/src/peer_connection/configuration.rs +++ b/webrtc/src/peer_connection/configuration.rs @@ -4,48 +4,58 @@ use crate::peer_connection::policy::bundle_policy::RTCBundlePolicy; use crate::peer_connection::policy::ice_transport_policy::RTCIceTransportPolicy; use crate::peer_connection::policy::rtcp_mux_policy::RTCRtcpMuxPolicy; -/// A Configuration defines how peer-to-peer communication via PeerConnection -/// is established or re-established. -/// Configurations may be set up once and reused across multiple connections. -/// Configurations are treated as readonly. As long as they are unmodified, -/// they are safe for concurrent use. +/// Defines a set of parameters to configure how the peer-to-peer communication via +/// [`RTCPeerConnection`] is established or re-established. These may be set up once +/// and reused across multiple connections, and are treated as readonly. As long as +/// they are unmodified, they are safe for concurrent use. +/// +/// [`RTCPeerConnection`]: crate::peer_connection::RTCPeerConnection #[derive(Default, Clone)] pub struct RTCConfiguration { - /// iceservers defines a slice describing servers available to be used by + /// Defines a slice describing servers available to be used by /// ICE, such as STUN and TURN servers. pub ice_servers: Vec, - /// icetransport_policy indicates which candidates the ICEAgent is allowed + /// Indicates which candidates the ICE Agent is allowed /// to use. pub ice_transport_policy: RTCIceTransportPolicy, - /// bundle_policy indicates which media-bundling policy to use when gathering + /// Indicates which media-bundling policy to use when gathering /// ICE candidates. pub bundle_policy: RTCBundlePolicy, - /// rtcp_mux_policy indicates which rtcp-mux policy to use when gathering ICE + /// Indicates which rtcp-mux policy to use when gathering ICE /// candidates. pub rtcp_mux_policy: RTCRtcpMuxPolicy, - /// peer_identity sets the target peer identity for the PeerConnection. + /// **UNIMPLEMENTED:** Sets the target peer identity for the [`RTCPeerConnection`]. /// The PeerConnection will not establish a connection to a remote peer /// unless it can be successfully authenticated with the provided name. + /// + /// [`RTCPeerConnection`]: crate::peer_connection::RTCPeerConnection pub peer_identity: String, - /// Certificates describes a set of certificates that the PeerConnection - /// uses to authenticate. Valid values for this parameter are created - /// through calls to the generate_certificate function. Although any given - /// DTLS connection will use only one certificate, this attribute allows the - /// caller to provide multiple certificates that support different - /// algorithms. The final certificate will be selected based on the DTLS - /// handshake, which establishes which certificates are allowed. The - /// PeerConnection implementation selects which of the certificates is + /// A set of certificates that the [`RTCPeerConnection`] uses to authenticate. + /// + /// Valid values for this parameter are created through calls to the + /// generate_certificate function. + /// + /// Although any given DTLS connection will use only one certificate, this + /// attribute allows the caller to provide multiple certificates that support + /// different algorithms. The final certificate will be selected based on the + /// DTLS handshake, which establishes which certificates are allowed. The + /// [`RTCPeerConnection`] implementation selects which of the certificates is /// used for a given connection; how certificates are selected is outside - /// the scope of this specification. If this value is absent, then a default - /// set of certificates is generated for each PeerConnection instance. + /// the scope of this specification. + /// + /// If this value is absent, then a default set of certificates is generated + /// for each [`RTCPeerConnection`] instance. + /// + /// [`RTCPeerConnection`]: crate::peer_connection::RTCPeerConnection pub certificates: Vec, - /// icecandidate_pool_size describes the size of the prefetched ICE pool. + /// **UNIMPLEMENTED:** The size of the prefetched ICE pool, as defined in + /// [RFC8829](https://tools.ietf.org/html/rfc8829). pub ice_candidate_pool_size: u8, } diff --git a/webrtc/src/peer_connection/mod.rs b/webrtc/src/peer_connection/mod.rs index b4989cef4..b4e5f8891 100644 --- a/webrtc/src/peer_connection/mod.rs +++ b/webrtc/src/peer_connection/mod.rs @@ -179,9 +179,10 @@ struct NegotiationNeededParams { check_negotiation_needed_params: CheckNegotiationNeededParams, } -/// PeerConnection represents a WebRTC connection that establishes a -/// peer-to-peer communications with another PeerConnection instance in a -/// browser, or to another endpoint implementing the required protocols. +/// Represents an individual connection between a local device and a remote peer. +/// +/// A high-level overview of how peer connections work is available in the [crate-level +/// documentation](crate). pub struct RTCPeerConnection { stats_id: String, idp_login_url: Option, diff --git a/webrtc/src/peer_connection/offer_answer_options.rs b/webrtc/src/peer_connection/offer_answer_options.rs index a7be6490b..8ad7b56e8 100644 --- a/webrtc/src/peer_connection/offer_answer_options.rs +++ b/webrtc/src/peer_connection/offer_answer_options.rs @@ -1,22 +1,24 @@ -/// AnswerOptions structure describes the options used to control the answer -/// creation process. +/// Describes the options used to control the answer creation process. #[derive(Default, Debug, PartialEq, Eq, Copy, Clone)] pub struct RTCAnswerOptions { - /// voice_activity_detection allows the application to provide information + /// Allows the application to provide information /// about whether it wishes voice detection feature to be enabled or disabled. pub voice_activity_detection: bool, } -/// OfferOptions structure describes the options used to control the offer -/// creation process +/// Describes the options used to control the offer creation process #[derive(Default, Debug, PartialEq, Eq, Copy, Clone)] pub struct RTCOfferOptions { - /// voice_activity_detection allows the application to provide information + /// Allows the application to provide information /// about whether it wishes voice detection feature to be enabled or disabled. pub voice_activity_detection: bool, - /// ice_restart forces the underlying ice gathering process to be restarted. - /// When this value is true, the generated description will have ICE - /// credentials that are different from the current credentials + /// When this value is `true`, the generated description will have ICE + /// credentials that are different from the current credentials. This + /// will result in the ICE connection being restarted when the offer is + /// applied. + /// + /// When this value is `false`, the generated description will have the + /// same ICE credentials as the current offer. This is the default. pub ice_restart: bool, } diff --git a/webrtc/src/peer_connection/peer_connection_state.rs b/webrtc/src/peer_connection/peer_connection_state.rs index 905e26769..a044e3af4 100644 --- a/webrtc/src/peer_connection/peer_connection_state.rs +++ b/webrtc/src/peer_connection/peer_connection_state.rs @@ -1,39 +1,63 @@ use std::fmt; -/// PeerConnectionState indicates the state of the PeerConnection. +/// Indicates the state of the [`RTCPeerConnection`]. +/// +/// [`RTCPeerConnection`]: crate::peer_connection::RTCPeerConnection #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] pub enum RTCPeerConnectionState { #[default] Unspecified, - /// PeerConnectionStateNew indicates that any of the ICETransports or - /// DTLSTransports are in the "new" state and none of the transports are - /// in the "connecting", "checking", "failed" or "disconnected" state, or - /// all transports are in the "closed" state, or there are no transports. - New, - - /// PeerConnectionStateConnecting indicates that any of the - /// ICETransports or DTLSTransports are in the "connecting" or - /// "checking" state and none of them is in the "failed" state. - Connecting, + /// Indicates that the [`RTCPeerConnection`] is closed + /// + /// [`RTCPeerConnection`]: crate::peer_connection::RTCPeerConnection + Closed, - /// PeerConnectionStateConnected indicates that all ICETransports and - /// DTLSTransports are in the "connected", "completed" or "closed" state - /// and at least one of them is in the "connected" or "completed" state. - Connected, + /// Indicates all of the following: + /// - the previous state does not apply + /// - any of the [`RTCIceTransport`]s or [`RTCDtlsTransport`]s + /// are in a `failed` state + /// + /// [`RTCDtlsTransport`]: crate::dtls_transport::RTCDtlsTransport + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + Failed, - /// PeerConnectionStateDisconnected indicates that any of the - /// ICETransports or DTLSTransports are in the "disconnected" state - /// and none of them are in the "failed" or "connecting" or "checking" state. + /// Indicates all of the following: + /// - none of the previous states apply + /// - any of the [`RTCIceTransport`]s are in the `disconnected` state + /// + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport Disconnected, - /// PeerConnectionStateFailed indicates that any of the ICETransports - /// or DTLSTransports are in a "failed" state. - Failed, + /// Indicates all of the following: + /// - none of the previous states apply + /// - all of the [`RTCIceTransport`]s are in the `new` or `closed` state + /// - all of the [`RTCDtlsTransport`]s (if any) are in the `new` or + /// `closed` state + /// + /// [`RTCDtlsTransport`]: crate::dtls_transport::RTCDtlsTransport + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + New, - /// PeerConnectionStateClosed indicates the peer connection is closed - /// and the isClosed member variable of PeerConnection is true. - Closed, + /// Indicates all of the following: + /// - none of the previous states apply + /// - any of the [`RTCIceTransport`]s are in the `new` or `checking` state, or + /// - any of the [`RTCDtlsTransport`]s are in the `new` or `connecting` state + /// + /// [`RTCDtlsTransport`]: crate::dtls_transport::RTCDtlsTransport + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + Connecting, + + /// Indicates all of the following: + /// - none of the previous states apply + /// - all of the [`RTCIceTransport`]s are in the `connected`, `completed`, or + /// `closed` state + /// - all of the [`RTCDtlsTransport`]s (if any) are in the `connected` or + /// `closed` state + /// + /// [`RTCDtlsTransport`]: crate::dtls_transport::RTCDtlsTransport + /// [`RTCIceTransport`]: crate::ice_transport::RTCIceTransport + Connected, } const PEER_CONNECTION_STATE_NEW_STR: &str = "new"; diff --git a/webrtc/src/peer_connection/policy/bundle_policy.rs b/webrtc/src/peer_connection/policy/bundle_policy.rs index 040228f26..f63fff8dc 100644 --- a/webrtc/src/peer_connection/policy/bundle_policy.rs +++ b/webrtc/src/peer_connection/policy/bundle_policy.rs @@ -2,8 +2,10 @@ use std::fmt; use serde::{Deserialize, Serialize}; -/// BundlePolicy affects which media tracks are negotiated if the remote -/// endpoint is not bundle-aware, and what ICE candidates are gathered. If the +/// The bundle policy +/// ([RFC8829](https://tools.ietf.org/html/rfc8829#section-4.1.1)) affects +/// which media tracks are negotiated if the remote endpoint is not +/// bundle-aware, and what ICE candidates are gathered. If the /// remote endpoint is bundle-aware, all media tracks and data channels are /// bundled onto the same transport. #[derive(Default, Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] @@ -11,20 +13,20 @@ pub enum RTCBundlePolicy { #[default] Unspecified = 0, - /// BundlePolicyBalanced indicates to gather ICE candidates for each + /// Gather ICE candidates for each /// media type in use (audio, video, and data). If the remote endpoint is /// not bundle-aware, negotiate only one audio and video track on separate /// transports. #[serde(rename = "balanced")] Balanced = 1, - /// BundlePolicyMaxCompat indicates to gather ICE candidates for each + /// Gather ICE candidates for each /// track. If the remote endpoint is not bundle-aware, negotiate all media /// tracks on separate transports. #[serde(rename = "max-compat")] MaxCompat = 2, - /// BundlePolicyMaxBundle indicates to gather ICE candidates for only + /// Gather ICE candidates for only /// one track. If the remote endpoint is not bundle-aware, negotiate only /// one media track. #[serde(rename = "max-bundle")] diff --git a/webrtc/src/peer_connection/policy/ice_transport_policy.rs b/webrtc/src/peer_connection/policy/ice_transport_policy.rs index 331ebe60b..e5101cf8e 100644 --- a/webrtc/src/peer_connection/policy/ice_transport_policy.rs +++ b/webrtc/src/peer_connection/policy/ice_transport_policy.rs @@ -2,26 +2,33 @@ use std::fmt; use serde::{Deserialize, Serialize}; -/// ICETransportPolicy defines the ICE candidate policy surface the -/// permitted candidates. Only these candidates are used for connectivity checks. +/// Defines the ICE candidate policy +/// ([RFC8829](https://tools.ietf.org/html/rfc8829#section-4.1.1)) +/// that will be used to determine the permitted ICE candidates. Only the +/// permitted candidates will be used for connectivity checks. #[derive(Default, Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] pub enum RTCIceTransportPolicy { #[default] Unspecified = 0, - /// ICETransportPolicyAll indicates any type of candidate is used. + /// Indicates that the ICE Agent can use any type of candidate. #[serde(rename = "all")] All = 1, - /// ICETransportPolicyRelay indicates only media relay candidates such - /// as candidates passing through a TURN server are used. + /// Indicates that the ICE Agent must use only media relay candidates, + /// such as candidates passing through a TURN server. + /// + /// This can be used to prevent the remote endpoint from learning the + /// user's IP addresses via STUN requests, which may be desirable in + /// certain use cases. + /// + /// Keep in mind that media relay candidates can increase latency, + /// reduce throughput, and consume more battery power than direct + /// peer-to-peer connections. #[serde(rename = "relay")] Relay = 2, } -/// ICEGatherPolicy is the ORTC equivalent of ICETransportPolicy -pub type ICEGatherPolicy = RTCIceTransportPolicy; - const ICE_TRANSPORT_POLICY_RELAY_STR: &str = "relay"; const ICE_TRANSPORT_POLICY_ALL_STR: &str = "all"; diff --git a/webrtc/src/peer_connection/policy/rtcp_mux_policy.rs b/webrtc/src/peer_connection/policy/rtcp_mux_policy.rs index 35ecccaae..98d93262c 100644 --- a/webrtc/src/peer_connection/policy/rtcp_mux_policy.rs +++ b/webrtc/src/peer_connection/policy/rtcp_mux_policy.rs @@ -2,21 +2,21 @@ use std::fmt; use serde::{Deserialize, Serialize}; -/// RTCPMuxPolicy affects what ICE candidates are gathered to support -/// non-multiplexed RTCP. +/// The mux policy [RFC8829](https://tools.ietf.org/html/rfc8829#section-4.1.1) +/// affects what ICE candidates are gathered to support non-multiplexed RTCP. #[derive(Default, Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] pub enum RTCRtcpMuxPolicy { #[default] Unspecified = 0, - /// RTCPMuxPolicyNegotiate indicates to gather ICE candidates for both + /// Gather ICE candidates for both /// RTP and RTCP candidates. If the remote-endpoint is capable of /// multiplexing RTCP, multiplex RTCP on the RTP candidates. If it is not, /// use both the RTP and RTCP candidates separately. #[serde(rename = "negotiate")] Negotiate = 1, - /// RTCPMuxPolicyRequire indicates to gather ICE candidates only for + /// Gather ICE candidates only for /// RTP and multiplex RTCP on the RTP candidates. If the remote endpoint is /// not capable of rtcp-mux, session negotiation will fail. #[serde(rename = "require")] diff --git a/webrtc/src/peer_connection/sdp/mod.rs b/webrtc/src/peer_connection/sdp/mod.rs index 28e3db15b..f5785629c 100644 --- a/webrtc/src/peer_connection/sdp/mod.rs +++ b/webrtc/src/peer_connection/sdp/mod.rs @@ -487,7 +487,7 @@ pub(crate) async fn add_transceiver_sdp( // We need to include connection information even if we're rejecting a track, otherwise Firefox will fail to // parse the SDP with an error like: // SIPCC Failed to parse SDP: SDP Parse Error on line 50: c= connection line not specified for every media level, validation failed. - // In addition this makes our SDP compliant with RFC 4566 Section 5.7: https://datatracker.ietf.org/doc/html/rfc4566#section-5.7 + // In addition this makes our SDP compliant with RFC 4566 Section 5.7: https://tools.ietf.org/html/rfc4566#section-5.7 connection_information: Some(ConnectionInformation { network_type: "IN".to_owned(), address_type: "IP4".to_owned(), @@ -557,7 +557,7 @@ pub(crate) async fn add_transceiver_sdp( // After we have include an msid attribute in an offer it must stay the same for // all subsequent offer even if the track or transceiver direction changes. // - // [RFC 8829 Section 5.2.2](https://datatracker.ietf.org/doc/html/rfc8829#section-5.2.2) + // [RFC 8829 Section 5.2.2](https://tools.ietf.org/html/rfc8829#section-5.2.2) // // For RtpTransceivers that are not stopped, the "a=msid" line or // lines MUST stay the same if they are present in the current @@ -604,7 +604,7 @@ pub(crate) async fn add_transceiver_sdp( // If don't have an offered direction to intersect with just use the transceivers // current direction. // - // https://datatracker.ietf.org/doc/html/rfc8829#section-4.2.3 + // https://tools.ietf.org/html/rfc8829#section-4.2.3 // // When creating offers, the transceiver direction is directly reflected // in the output, even for re-offers. diff --git a/webrtc/src/peer_connection/sdp/sdp_type.rs b/webrtc/src/peer_connection/sdp/sdp_type.rs index 830864f79..585189b27 100644 --- a/webrtc/src/peer_connection/sdp/sdp_type.rs +++ b/webrtc/src/peer_connection/sdp/sdp_type.rs @@ -2,36 +2,35 @@ use std::fmt; use serde::{Deserialize, Serialize}; -/// SDPType describes the type of an SessionDescription. +/// Describes the type of an SDP message #[derive(Default, Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] pub enum RTCSdpType { #[default] + #[serde(rename = "Unspecified")] Unspecified = 0, - /// indicates that a description MUST be treated as an SDP offer. - #[serde(rename = "offer")] + /// Indicates that a description MUST be treated as an SDP offer. Offer, - /// indicates that a description MUST be treated as an + /// Indicates that a description MUST be treated as an /// SDP answer, but not a final answer. A description used as an SDP /// pranswer may be applied as a response to an SDP offer, or an update to /// a previously sent SDP pranswer. - #[serde(rename = "pranswer")] Pranswer, - /// indicates that a description MUST be treated as an SDP + /// Indicates that a description MUST be treated as an SDP /// final answer, and the offer-answer exchange MUST be considered complete. /// A description used as an SDP answer may be applied as a response to an - /// SDP offer or as an update to a previously sent SDP pranswer. - #[serde(rename = "answer")] + /// SDP offer or as an update to a previously sent SDP pranswer. Answer, - /// indicates that a description MUST be treated as + /// Indicates that a description MUST be treated as /// canceling the current SDP negotiation and moving the SDP offer and /// answer back to what it was in the previous stable state. Note the /// local or remote SDP descriptions in the previous stable state could be - /// null if there has not yet been a successful offer-answer negotiation. - #[serde(rename = "rollback")] + /// `None` if there has not yet been a successful offer-answer negotiation. + /// An answer or pranswer cannot be rolled back. Rollback, } diff --git a/webrtc/src/peer_connection/signaling_state.rs b/webrtc/src/peer_connection/signaling_state.rs index 2edd613be..1683799a9 100644 --- a/webrtc/src/peer_connection/signaling_state.rs +++ b/webrtc/src/peer_connection/signaling_state.rs @@ -20,36 +20,38 @@ impl fmt::Display for StateChangeOp { } } -/// SignalingState indicates the signaling state of the offer/answer process. +/// Indicates the signaling state of the offer/answer process. #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] pub enum RTCSignalingState { #[default] Unspecified = 0, - /// SignalingStateStable indicates there is no offer/answer exchange in + /// There is no offer/answer exchange in /// progress. This is also the initial state, in which case the local and - /// remote descriptions are nil. + /// remote descriptions aren't set. Stable, - /// SignalingStateHaveLocalOffer indicates that a local description, of - /// type "offer", has been successfully applied. + /// A local description, of + /// type `offer`, has been successfully applied. HaveLocalOffer, - /// SignalingStateHaveRemoteOffer indicates that a remote description, of - /// type "offer", has been successfully applied. + /// A remote description, of + /// type `offer`, has been successfully applied. HaveRemoteOffer, - /// SignalingStateHaveLocalPranswer indicates that a remote description - /// of type "offer" has been successfully applied and a local description - /// of type "pranswer" has been successfully applied. + /// A remote description + /// of type `offer` has been successfully applied and a local description + /// of type `pranswer` has been successfully applied. HaveLocalPranswer, - /// SignalingStateHaveRemotePranswer indicates that a local description - /// of type "offer" has been successfully applied and a remote description - /// of type "pranswer" has been successfully applied. + /// A local description + /// of type `offer` has been successfully applied and a remote description + /// of type `pranswer` has been successfully applied. HaveRemotePranswer, - /// SignalingStateClosed indicates The PeerConnection has been closed. + /// The [`RTCPeerConnection`] has been closed. + /// + /// [`RTCPeerConnection`]: crate::peer_connection::RTCPeerConnection Closed, }