pub struct SdpApi<'a> { /* private fields */ }
Expand description
Changes to the Rtc via SDP Offer/Answer dance.
Implementations§
Source§impl<'a> SdpApi<'a>
impl<'a> SdpApi<'a>
Sourcepub fn accept_offer(self, offer: SdpOffer) -> Result<SdpAnswer, RtcError>
pub fn accept_offer(self, offer: SdpOffer) -> Result<SdpAnswer, RtcError>
Accept an SdpOffer
from the remote peer. If this call returns successfully, the
changes will have been made to the session. The resulting SdpAnswer
should be
sent to the remote peer.
Note. Pending changes from a previous non-completed SdpApi
will be
considered rolled back when calling this function.
The incoming SDP is validated in various ways which can cause this call to fail.
Example of such problems would be an SDP without any m-lines, missing a=fingerprint
or if a=group
doesn’t match the number of m-lines.
// obtain offer from remote peer.
let json_offer: &[u8] = todo!();
let offer: SdpOffer = serde_json::from_slice(json_offer).unwrap();
let mut rtc = Rtc::new();
let answer = rtc.sdp_api().accept_offer(offer).unwrap();
// send json_answer to remote peer.
let json_answer = serde_json::to_vec(&answer).unwrap();
Sourcepub fn accept_answer(
self,
pending: SdpPendingOffer,
answer: SdpAnswer,
) -> Result<(), RtcError>
pub fn accept_answer( self, pending: SdpPendingOffer, answer: SdpAnswer, ) -> Result<(), RtcError>
Accept an answer to a previously created SdpOffer
.
This function returns an RtcError::ChangesOutOfOrder
if we have created and applied another
SdpApi
before calling this. The same also happens if we use
SdpApi::accept_offer()
before using this pending instance.
let mut rtc = Rtc::new();
let mut changes = rtc.sdp_api();
let mid = changes.add_media(MediaKind::Audio, Direction::SendOnly, None, None);
let (offer, pending) = changes.apply().unwrap();
// send offer to remote peer, receive answer back
let answer: SdpAnswer = todo!();
rtc.sdp_api().accept_answer(pending, answer).unwrap();
Sourcepub fn has_changes(&self) -> bool
pub fn has_changes(&self) -> bool
Test if any changes have been made.
If changes have been made, nothing happens until we call SdpApi::apply()
.
let mut rtc = Rtc::new();
let mut changes = rtc.sdp_api();
assert!(!changes.has_changes());
let mid = changes.add_media(MediaKind::Audio, Direction::SendRecv, None, None);
assert!(changes.has_changes());
Sourcepub fn add_media(
&mut self,
kind: MediaKind,
dir: Direction,
stream_id: Option<String>,
track_id: Option<String>,
) -> Mid
pub fn add_media( &mut self, kind: MediaKind, dir: Direction, stream_id: Option<String>, track_id: Option<String>, ) -> Mid
Add audio or video media and get the mid
that will be used.
Each call will result in a new m-line in the offer identified by the Mid
.
The mid is not valid to use until the SDP offer-answer dance is complete and
the mid been advertised via Event::MediaAdded
.
stream_id
is used to synchronize media. It isa=msid-semantic: WMS <streamId>
line in SDP.track_id
is becomes both the track id ina=msid <streamId> <trackId>
as well as the CNAME in the RTP SDES.
let mut rtc = Rtc::new();
let mut changes = rtc.sdp_api();
let mid = changes.add_media(MediaKind::Audio, Direction::SendRecv, None, None);
Sourcepub fn set_direction(&mut self, mid: Mid, dir: Direction)
pub fn set_direction(&mut self, mid: Mid, dir: Direction)
Change the direction of an already existing media.
All media have a direction. The media can be added by this side via
SdpApi::add_media()
or by the remote peer. Either way, the direction
of the line can be changed at any time.
It’s possible to set the direction Direction::Inactive
for media that
will not be used by the session anymore.
If the direction is set for media that doesn’t exist, or if the direction is
the same that’s already set SdpApi::apply()
not require a negotiation.
Sourcepub fn add_channel(&mut self, label: String) -> ChannelId
pub fn add_channel(&mut self, label: String) -> ChannelId
Add a new data channel and get the id
that will be used.
The first ever data channel added to a WebRTC session results in a media of a special “application” type in the SDP. The m-line is for a SCTP association over DTLS, and all data channels are multiplexed over this single association.
That means only the first ever add_channel
will result in an SdpOffer
.
Consecutive channels will be opened without needing a negotiation.
The label is used to identify the data channel to the remote peer. This is mostly useful whe multiple channels are in use at the same time.
let mut rtc = Rtc::new();
let mut changes = rtc.sdp_api();
let cid = changes.add_channel("my special channel".to_string());
Sourcepub fn ice_restart(&mut self, keep_local_candidates: bool) -> IceCreds
pub fn ice_restart(&mut self, keep_local_candidates: bool) -> IceCreds
Perform an ICE restart.
Only one ICE restart can be pending at the time. Calling this repeatedly removes any other pending ICE restart.
The local ICE candidates can be kept as is, or be cleared out, in which case new ice
candidates must be added via Rtc::add_local_candidate
before connectivity can be
re-established.
Returns the new ICE credentials that will be used going forward.
Sourcepub fn apply(self) -> Option<(SdpOffer, SdpPendingOffer)>
pub fn apply(self) -> Option<(SdpOffer, SdpPendingOffer)>
Attempt to apply the changes made.
If this returns SdpOffer
, the caller the changes are
not happening straight away, and the caller is expected to do a negotiation with the remote
peer and apply the answer using SdpPendingOffer
.
In case this returns None
, there either were no changes, or the changes could be applied
without doing a negotiation. Specifically for additional SdpApi::add_channel()
after the first, there is no negotiation needed.
The SdpPendingOffer
is valid until the next time we call this function, at which
point using it will raise an error. Using SdpApi::accept_offer()
will also invalidate
the current SdpPendingOffer
.
let mut rtc = Rtc::new();
let changes = rtc.sdp_api();
assert!(changes.apply().is_none());
Sourcepub fn merge(&mut self, pending_offer: SdpPendingOffer)
pub fn merge(&mut self, pending_offer: SdpPendingOffer)
Combines the modifications made in SdpApi
with those in SdpPendingOffer
.
This function merges the changes present in SdpApi
with the changes
in SdpPendingOffer
. In result this SdpApi
will incorporate modifications
from both the previous SdpPendingOffer
and any newly added changes.
§Example
let mut rtc = Rtc::new();
let mut changes = rtc.sdp_api();
changes.add_media(MediaKind::Audio, Direction::SendOnly, None, None);
let (_offer, pending) = changes.apply().unwrap();
let mut changes = rtc.sdp_api();
changes.add_media(MediaKind::Video, Direction::SendOnly, None, None);
changes.merge(pending);
// This `SdpOffer` will have changes from the first `SdpPendingChanges`
// and new changes from `SdpApi`
let (_offer, pending) = changes.apply().unwrap();