/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use libc::{c_float, size_t}; use std::ptr; use std::slice; use nserror::{nsresult, NS_ERROR_INVALID_ARG, NS_OK}; use rsdparsa::attribute_type::*; use rsdparsa::SdpSession; use network::{RustAddress, RustExplicitlyTypedAddress}; use types::StringView; #[no_mangle] pub unsafe extern "C" fn num_attributes(session: *const SdpSession) -> u32 { (*session).attribute.len() as u32 } #[no_mangle] pub unsafe extern "C" fn get_attribute_ptr( session: *const SdpSession, index: u32, ret: *mut *const SdpAttribute, ) -> nsresult { match (*session).attribute.get(index as usize) { Some(attribute) => { *ret = attribute as *const SdpAttribute; NS_OK } None => NS_ERROR_INVALID_ARG, } } fn count_attribute(attributes: &[SdpAttribute], search: SdpAttributeType) -> usize { let mut count = 0; for attribute in (*attributes).iter() { if SdpAttributeType::from(attribute) == search { count += 1; } } count } fn argsearch(attributes: &[SdpAttribute], attribute_type: SdpAttributeType) -> Option { for (i, attribute) in (*attributes).iter().enumerate() { if SdpAttributeType::from(attribute) == attribute_type { return Some(i); } } None } pub unsafe fn has_attribute( attributes: *const Vec, attribute_type: SdpAttributeType, ) -> bool { argsearch((*attributes).as_slice(), attribute_type).is_some() } fn get_attribute( attributes: &[SdpAttribute], attribute_type: SdpAttributeType, ) -> Option<&SdpAttribute> { argsearch(attributes, attribute_type).map(|i| &attributes[i]) } #[repr(C)] #[derive(Clone, Copy)] pub enum RustSdpAttributeDtlsMessageType { Client, Server, } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeDtlsMessage { pub role: u8, pub value: StringView, } impl<'a> From<&'a SdpAttributeDtlsMessage> for RustSdpAttributeDtlsMessage { fn from(other: &SdpAttributeDtlsMessage) -> Self { match other { &SdpAttributeDtlsMessage::Client(ref x) => RustSdpAttributeDtlsMessage { role: RustSdpAttributeDtlsMessageType::Client as u8, value: StringView::from(x.as_str()), }, &SdpAttributeDtlsMessage::Server(ref x) => RustSdpAttributeDtlsMessage { role: RustSdpAttributeDtlsMessageType::Server as u8, value: StringView::from(x.as_str()), }, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_dtls_message( attributes: *const Vec, ret: *mut RustSdpAttributeDtlsMessage, ) -> nsresult { let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::DtlsMessage); if let Some(&SdpAttribute::DtlsMessage(ref dtls_message)) = attr { *ret = RustSdpAttributeDtlsMessage::from(dtls_message); return NS_OK; } NS_ERROR_INVALID_ARG } #[no_mangle] pub unsafe extern "C" fn sdp_get_iceufrag( attributes: *const Vec, ret: *mut StringView, ) -> nsresult { let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::IceUfrag); if let Some(&SdpAttribute::IceUfrag(ref string)) = attr { *ret = StringView::from(string.as_str()); return NS_OK; } NS_ERROR_INVALID_ARG } #[no_mangle] pub unsafe extern "C" fn sdp_get_icepwd( attributes: *const Vec, ret: *mut StringView, ) -> nsresult { let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::IcePwd); if let Some(&SdpAttribute::IcePwd(ref string)) = attr { *ret = StringView::from(string.as_str()); return NS_OK; } NS_ERROR_INVALID_ARG } #[no_mangle] pub unsafe extern "C" fn sdp_get_identity( attributes: *const Vec, ret: *mut StringView, ) -> nsresult { let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::Identity); if let Some(&SdpAttribute::Identity(ref string)) = attr { *ret = StringView::from(string.as_str()); return NS_OK; } NS_ERROR_INVALID_ARG } #[no_mangle] pub unsafe extern "C" fn sdp_get_iceoptions( attributes: *const Vec, ret: *mut *const Vec, ) -> nsresult { let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::IceOptions); if let Some(&SdpAttribute::IceOptions(ref options)) = attr { *ret = options; return NS_OK; } NS_ERROR_INVALID_ARG } #[no_mangle] pub unsafe extern "C" fn sdp_get_maxptime( attributes: *const Vec, ret: *mut u64, ) -> nsresult { let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::MaxPtime); if let Some(&SdpAttribute::MaxPtime(ref max_ptime)) = attr { *ret = *max_ptime; return NS_OK; } NS_ERROR_INVALID_ARG } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeFingerprint { hash_algorithm: u16, fingerprint: *const Vec, } impl<'a> From<&'a SdpAttributeFingerprint> for RustSdpAttributeFingerprint { fn from(other: &SdpAttributeFingerprint) -> Self { RustSdpAttributeFingerprint { hash_algorithm: other.hash_algorithm as u16, fingerprint: &other.fingerprint, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_fingerprint_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Fingerprint) } #[no_mangle] pub unsafe extern "C" fn sdp_get_fingerprints( attributes: *const Vec, ret_size: size_t, ret_fingerprints: *mut RustSdpAttributeFingerprint, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Fingerprint(ref data) = *x { Some(RustSdpAttributeFingerprint::from(data)) } else { None } }) .collect(); let fingerprints = slice::from_raw_parts_mut(ret_fingerprints, ret_size); fingerprints.copy_from_slice(attrs.as_slice()); } #[repr(C)] #[derive(Clone)] pub enum RustSdpAttributeSetup { Active, Actpass, Holdconn, Passive, } impl<'a> From<&'a SdpAttributeSetup> for RustSdpAttributeSetup { fn from(other: &SdpAttributeSetup) -> Self { match *other { SdpAttributeSetup::Active => RustSdpAttributeSetup::Active, SdpAttributeSetup::Actpass => RustSdpAttributeSetup::Actpass, SdpAttributeSetup::Holdconn => RustSdpAttributeSetup::Holdconn, SdpAttributeSetup::Passive => RustSdpAttributeSetup::Passive, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_setup( attributes: *const Vec, ret: *mut RustSdpAttributeSetup, ) -> nsresult { let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::Setup); if let Some(&SdpAttribute::Setup(ref setup)) = attr { *ret = RustSdpAttributeSetup::from(setup); return NS_OK; } NS_ERROR_INVALID_ARG } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeSsrc { pub id: u32, pub attribute: StringView, pub value: StringView, } impl<'a> From<&'a SdpAttributeSsrc> for RustSdpAttributeSsrc { fn from(other: &SdpAttributeSsrc) -> Self { RustSdpAttributeSsrc { id: other.id, attribute: StringView::from(&other.attribute), value: StringView::from(&other.value), } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_ssrc_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Ssrc) } #[no_mangle] pub unsafe extern "C" fn sdp_get_ssrcs( attributes: *const Vec, ret_size: size_t, ret_ssrcs: *mut RustSdpAttributeSsrc, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Ssrc(ref data) = *x { Some(RustSdpAttributeSsrc::from(data)) } else { None } }) .collect(); let ssrcs = slice::from_raw_parts_mut(ret_ssrcs, ret_size); ssrcs.copy_from_slice(attrs.as_slice()); } #[repr(C)] #[derive(Clone, Copy)] pub enum RustSdpSsrcGroupSemantic { Duplication, FlowIdentification, ForwardErrorCorrection, ForwardErrorCorrectionFr, SIM, } impl<'a> From<&'a SdpSsrcGroupSemantic> for RustSdpSsrcGroupSemantic { fn from(other: &SdpSsrcGroupSemantic) -> Self { match *other { SdpSsrcGroupSemantic::Duplication => RustSdpSsrcGroupSemantic::Duplication, SdpSsrcGroupSemantic::FlowIdentification => { RustSdpSsrcGroupSemantic::FlowIdentification } SdpSsrcGroupSemantic::ForwardErrorCorrection => { RustSdpSsrcGroupSemantic::ForwardErrorCorrection } SdpSsrcGroupSemantic::ForwardErrorCorrectionFr => { RustSdpSsrcGroupSemantic::ForwardErrorCorrectionFr } SdpSsrcGroupSemantic::Sim => RustSdpSsrcGroupSemantic::SIM, } } } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpSsrcGroup { pub semantic: RustSdpSsrcGroupSemantic, pub ssrcs: *const Vec, } #[no_mangle] pub unsafe extern "C" fn sdp_get_ssrc_group_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::SsrcGroup) } #[no_mangle] pub unsafe extern "C" fn sdp_get_ssrc_groups( attributes: *const Vec, ret_size: size_t, ret_ssrc_groups: *mut RustSdpSsrcGroup, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::SsrcGroup(ref semantic, ref ssrcs) = *x { Some(RustSdpSsrcGroup { semantic: RustSdpSsrcGroupSemantic::from(semantic), ssrcs: ssrcs, }) } else { None } }) .collect(); let ssrc_groups = slice::from_raw_parts_mut(ret_ssrc_groups, ret_size); ssrc_groups.copy_from_slice(attrs.as_slice()); } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeRtpmap { pub payload_type: u8, pub codec_name: StringView, pub frequency: u32, pub channels: u32, } impl<'a> From<&'a SdpAttributeRtpmap> for RustSdpAttributeRtpmap { fn from(other: &SdpAttributeRtpmap) -> Self { RustSdpAttributeRtpmap { payload_type: other.payload_type as u8, codec_name: StringView::from(other.codec_name.as_str()), frequency: other.frequency as u32, channels: other.channels.unwrap_or(0), } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_rtpmap_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Rtpmap) } #[no_mangle] pub unsafe extern "C" fn sdp_get_rtpmaps( attributes: *const Vec, ret_size: size_t, ret_rtpmaps: *mut RustSdpAttributeRtpmap, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Rtpmap(ref data) = *x { Some(RustSdpAttributeRtpmap::from(data)) } else { None } }) .collect(); let rtpmaps = slice::from_raw_parts_mut(ret_rtpmaps, ret_size); rtpmaps.copy_from_slice(attrs.as_slice()); } #[repr(C)] #[derive(Clone, Copy)] pub struct RustRtxFmtpParameters { pub apt: u8, pub has_rtx_time: bool, pub rtx_time: u32, } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeFmtpParameters { // H264 pub packetization_mode: u32, pub level_asymmetry_allowed: bool, pub profile_level_id: u32, pub max_fs: u32, pub max_cpb: u32, pub max_dpb: u32, pub max_br: u32, pub max_mbps: u32, // VP8 and VP9 // max_fs, already defined in H264 pub max_fr: u32, // Opus pub maxplaybackrate: u32, pub maxaveragebitrate: u32, pub usedtx: bool, pub stereo: bool, pub useinbandfec: bool, pub cbr: bool, pub ptime: u32, pub minptime: u32, pub maxptime: u32, // telephone-event pub dtmf_tones: StringView, // RTX pub rtx: RustRtxFmtpParameters, // Red pub encodings: *const Vec, // Unknown pub unknown_tokens: *const Vec, } impl<'a> From<&'a SdpAttributeFmtpParameters> for RustSdpAttributeFmtpParameters { fn from(other: &SdpAttributeFmtpParameters) -> Self { let rtx = if let Some(rtx) = other.rtx { RustRtxFmtpParameters { apt: rtx.apt, has_rtx_time: rtx.rtx_time.is_some(), rtx_time: rtx.rtx_time.unwrap_or(0), } } else { RustRtxFmtpParameters { apt: 0, has_rtx_time: false, rtx_time: 0, } }; RustSdpAttributeFmtpParameters { packetization_mode: other.packetization_mode, level_asymmetry_allowed: other.level_asymmetry_allowed, profile_level_id: other.profile_level_id, max_fs: other.max_fs, max_cpb: other.max_cpb, max_dpb: other.max_dpb, max_br: other.max_br, max_mbps: other.max_mbps, usedtx: other.usedtx, stereo: other.stereo, useinbandfec: other.useinbandfec, cbr: other.cbr, max_fr: other.max_fr, maxplaybackrate: other.maxplaybackrate, maxaveragebitrate: other.maxaveragebitrate, ptime: other.ptime, minptime: other.minptime, maxptime: other.maxptime, dtmf_tones: StringView::from(other.dtmf_tones.as_str()), rtx, encodings: &other.encodings, unknown_tokens: &other.unknown_tokens, } } } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeFmtp { pub payload_type: u8, pub codec_name: StringView, pub parameters: RustSdpAttributeFmtpParameters, } #[no_mangle] pub unsafe extern "C" fn sdp_get_fmtp_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Fmtp) } fn find_payload_type(attributes: &[SdpAttribute], payload_type: u8) -> Option<&SdpAttributeRtpmap> { attributes .iter() .filter_map(|x| { if let SdpAttribute::Rtpmap(ref data) = *x { if data.payload_type == payload_type { Some(data) } else { None } } else { None } }) .next() } #[no_mangle] pub unsafe extern "C" fn sdp_get_fmtp( attributes: *const Vec, ret_size: size_t, ret_fmtp: *mut RustSdpAttributeFmtp, ) -> size_t { let fmtps = (*attributes).iter().filter_map(|x| { if let SdpAttribute::Fmtp(ref data) = *x { Some(data) } else { None } }); let mut rust_fmtps = Vec::new(); for fmtp in fmtps { if let Some(rtpmap) = find_payload_type((*attributes).as_slice(), fmtp.payload_type) { rust_fmtps.push(RustSdpAttributeFmtp { payload_type: fmtp.payload_type as u8, codec_name: StringView::from(rtpmap.codec_name.as_str()), parameters: RustSdpAttributeFmtpParameters::from(&fmtp.parameters), }); } } let fmtps = if ret_size <= rust_fmtps.len() { slice::from_raw_parts_mut(ret_fmtp, ret_size) } else { slice::from_raw_parts_mut(ret_fmtp, rust_fmtps.len()) }; fmtps.copy_from_slice(rust_fmtps.as_slice()); fmtps.len() } #[no_mangle] pub unsafe extern "C" fn sdp_get_ptime(attributes: *const Vec) -> i64 { for attribute in (*attributes).iter() { if let SdpAttribute::Ptime(time) = *attribute { return time as i64; } } -1 } #[no_mangle] pub unsafe extern "C" fn sdp_get_max_msg_size(attributes: *const Vec) -> i64 { for attribute in (*attributes).iter() { if let SdpAttribute::MaxMessageSize(max_msg_size) = *attribute { return max_msg_size as i64; } } -1 } #[no_mangle] pub unsafe extern "C" fn sdp_get_sctp_port(attributes: *const Vec) -> i64 { for attribute in (*attributes).iter() { if let SdpAttribute::SctpPort(port) = *attribute { return port as i64; } } -1 } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeFlags { pub ice_lite: bool, pub rtcp_mux: bool, pub rtcp_rsize: bool, pub bundle_only: bool, pub end_of_candidates: bool, } #[no_mangle] pub unsafe extern "C" fn sdp_get_attribute_flags( attributes: *const Vec, ) -> RustSdpAttributeFlags { let mut ret = RustSdpAttributeFlags { ice_lite: false, rtcp_mux: false, rtcp_rsize: false, bundle_only: false, end_of_candidates: false, }; for attribute in (*attributes).iter() { if let SdpAttribute::IceLite = *attribute { ret.ice_lite = true; } else if let SdpAttribute::RtcpMux = *attribute { ret.rtcp_mux = true; } else if let SdpAttribute::RtcpRsize = *attribute { ret.rtcp_rsize = true; } else if let SdpAttribute::BundleOnly = *attribute { ret.bundle_only = true; } else if let SdpAttribute::EndOfCandidates = *attribute { ret.end_of_candidates = true; } } ret } #[no_mangle] pub unsafe extern "C" fn sdp_get_mid( attributes: *const Vec, ret: *mut StringView, ) -> nsresult { for attribute in (*attributes).iter() { if let SdpAttribute::Mid(ref data) = *attribute { *ret = StringView::from(data.as_str()); return NS_OK; } } NS_ERROR_INVALID_ARG } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeMsid { id: StringView, appdata: StringView, } impl<'a> From<&'a SdpAttributeMsid> for RustSdpAttributeMsid { fn from(other: &SdpAttributeMsid) -> Self { RustSdpAttributeMsid { id: StringView::from(other.id.as_str()), appdata: StringView::from(&other.appdata), } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_msid_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Msid) } #[no_mangle] pub unsafe extern "C" fn sdp_get_msids( attributes: *const Vec, ret_size: size_t, ret_msids: *mut RustSdpAttributeMsid, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Msid(ref data) = *x { Some(RustSdpAttributeMsid::from(data)) } else { None } }) .collect(); let msids = slice::from_raw_parts_mut(ret_msids, ret_size); msids.copy_from_slice(attrs.as_slice()); } // TODO: Finish msid attributes once parsing is changed upstream. #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeMsidSemantic { pub semantic: StringView, pub msids: *const Vec, } impl<'a> From<&'a SdpAttributeMsidSemantic> for RustSdpAttributeMsidSemantic { fn from(other: &SdpAttributeMsidSemantic) -> Self { RustSdpAttributeMsidSemantic { semantic: StringView::from(other.semantic.as_str()), msids: &other.msids, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_msid_semantic_count( attributes: *const Vec, ) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::MsidSemantic) } #[no_mangle] pub unsafe extern "C" fn sdp_get_msid_semantics( attributes: *const Vec, ret_size: size_t, ret_msid_semantics: *mut RustSdpAttributeMsidSemantic, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::MsidSemantic(ref data) = *x { Some(RustSdpAttributeMsidSemantic::from(data)) } else { None } }) .collect(); let msid_semantics = slice::from_raw_parts_mut(ret_msid_semantics, ret_size); msid_semantics.copy_from_slice(attrs.as_slice()); } #[repr(C)] #[derive(Clone, Copy)] pub enum RustSdpAttributeGroupSemantic { LipSynchronization, FlowIdentification, SingleReservationFlow, AlternateNetworkAddressType, ForwardErrorCorrection, DecodingDependency, Bundle, } impl<'a> From<&'a SdpAttributeGroupSemantic> for RustSdpAttributeGroupSemantic { fn from(other: &SdpAttributeGroupSemantic) -> Self { match *other { SdpAttributeGroupSemantic::LipSynchronization => { RustSdpAttributeGroupSemantic::LipSynchronization } SdpAttributeGroupSemantic::FlowIdentification => { RustSdpAttributeGroupSemantic::FlowIdentification } SdpAttributeGroupSemantic::SingleReservationFlow => { RustSdpAttributeGroupSemantic::SingleReservationFlow } SdpAttributeGroupSemantic::AlternateNetworkAddressType => { RustSdpAttributeGroupSemantic::AlternateNetworkAddressType } SdpAttributeGroupSemantic::ForwardErrorCorrection => { RustSdpAttributeGroupSemantic::ForwardErrorCorrection } SdpAttributeGroupSemantic::DecodingDependency => { RustSdpAttributeGroupSemantic::DecodingDependency } SdpAttributeGroupSemantic::Bundle => RustSdpAttributeGroupSemantic::Bundle, } } } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeGroup { pub semantic: RustSdpAttributeGroupSemantic, pub tags: *const Vec, } impl<'a> From<&'a SdpAttributeGroup> for RustSdpAttributeGroup { fn from(other: &SdpAttributeGroup) -> Self { RustSdpAttributeGroup { semantic: RustSdpAttributeGroupSemantic::from(&other.semantics), tags: &other.tags, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_group_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Group) } #[no_mangle] pub unsafe extern "C" fn sdp_get_groups( attributes: *const Vec, ret_size: size_t, ret_groups: *mut RustSdpAttributeGroup, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Group(ref data) = *x { Some(RustSdpAttributeGroup::from(data)) } else { None } }) .collect(); let groups = slice::from_raw_parts_mut(ret_groups, ret_size); groups.copy_from_slice(attrs.as_slice()); } #[repr(C)] pub struct RustSdpAttributeRtcp { pub port: u32, pub unicast_addr: RustExplicitlyTypedAddress, pub has_address: bool, } impl<'a> From<&'a SdpAttributeRtcp> for RustSdpAttributeRtcp { fn from(other: &SdpAttributeRtcp) -> Self { match other.unicast_addr { Some(ref address) => RustSdpAttributeRtcp { port: other.port as u32, unicast_addr: address.into(), has_address: true, }, None => RustSdpAttributeRtcp { port: other.port as u32, unicast_addr: RustExplicitlyTypedAddress::default(), has_address: false, }, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_rtcp( attributes: *const Vec, ret: *mut RustSdpAttributeRtcp, ) -> nsresult { let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::Rtcp); if let Some(&SdpAttribute::Rtcp(ref data)) = attr { *ret = RustSdpAttributeRtcp::from(data); return NS_OK; } NS_ERROR_INVALID_ARG } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeRtcpFb { pub payload_type: u32, pub feedback_type: u32, pub parameter: StringView, pub extra: StringView, } impl<'a> From<&'a SdpAttributeRtcpFb> for RustSdpAttributeRtcpFb { fn from(other: &SdpAttributeRtcpFb) -> Self { RustSdpAttributeRtcpFb { payload_type: match other.payload_type { SdpAttributePayloadType::Wildcard => u32::max_value(), SdpAttributePayloadType::PayloadType(x) => x as u32, }, feedback_type: other.feedback_type.clone() as u32, parameter: StringView::from(other.parameter.as_str()), extra: StringView::from(other.extra.as_str()), } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_rtcpfb_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Rtcpfb) } #[no_mangle] pub unsafe extern "C" fn sdp_get_rtcpfbs( attributes: *const Vec, ret_size: size_t, ret_rtcpfbs: *mut RustSdpAttributeRtcpFb, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Rtcpfb(ref data) = *x { Some(RustSdpAttributeRtcpFb::from(data)) } else { None } }) .collect(); let rtcpfbs = slice::from_raw_parts_mut(ret_rtcpfbs, ret_size); rtcpfbs.clone_from_slice(attrs.as_slice()); } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeImageAttrXyRange { // range pub min: u32, pub max: u32, pub step: u32, // discrete values pub discrete_values: *const Vec, } impl<'a> From<&'a SdpAttributeImageAttrXyRange> for RustSdpAttributeImageAttrXyRange { fn from(other: &SdpAttributeImageAttrXyRange) -> Self { match other { &SdpAttributeImageAttrXyRange::Range(min, max, step) => { RustSdpAttributeImageAttrXyRange { min, max, step: step.unwrap_or(1), discrete_values: ptr::null(), } } &SdpAttributeImageAttrXyRange::DiscreteValues(ref discrete_values) => { RustSdpAttributeImageAttrXyRange { min: 0, max: 1, step: 1, discrete_values, } } } } } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeImageAttrSRange { // range pub min: c_float, pub max: c_float, // discrete values pub discrete_values: *const Vec, } impl<'a> From<&'a SdpAttributeImageAttrSRange> for RustSdpAttributeImageAttrSRange { fn from(other: &SdpAttributeImageAttrSRange) -> Self { match other { &SdpAttributeImageAttrSRange::Range(min, max) => RustSdpAttributeImageAttrSRange { min, max, discrete_values: ptr::null(), }, &SdpAttributeImageAttrSRange::DiscreteValues(ref discrete_values) => { RustSdpAttributeImageAttrSRange { min: 0.0, max: 1.0, discrete_values, } } } } } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeImageAttrPRange { pub min: c_float, pub max: c_float, } impl<'a> From<&'a SdpAttributeImageAttrPRange> for RustSdpAttributeImageAttrPRange { fn from(other: &SdpAttributeImageAttrPRange) -> Self { RustSdpAttributeImageAttrPRange { min: other.min, max: other.max, } } } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeImageAttrSet { pub x: RustSdpAttributeImageAttrXyRange, pub y: RustSdpAttributeImageAttrXyRange, pub has_sar: bool, pub sar: RustSdpAttributeImageAttrSRange, pub has_par: bool, pub par: RustSdpAttributeImageAttrPRange, pub q: c_float, } impl<'a> From<&'a SdpAttributeImageAttrSet> for RustSdpAttributeImageAttrSet { fn from(other: &SdpAttributeImageAttrSet) -> Self { RustSdpAttributeImageAttrSet { x: RustSdpAttributeImageAttrXyRange::from(&other.x), y: RustSdpAttributeImageAttrXyRange::from(&other.y), has_sar: other.sar.is_some(), sar: match other.sar { Some(ref x) => RustSdpAttributeImageAttrSRange::from(x), // This is just any valid value accepted by rust, // it might as well by uninitilized None => RustSdpAttributeImageAttrSRange::from( &SdpAttributeImageAttrSRange::DiscreteValues(vec![]), ), }, has_par: other.par.is_some(), par: match other.par { Some(ref x) => RustSdpAttributeImageAttrPRange::from(x), // This is just any valid value accepted by rust, // it might as well by uninitilized None => RustSdpAttributeImageAttrPRange { min: 0.0, max: 1.0 }, }, q: other.q.unwrap_or(0.5), } } } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeImageAttrSetList { pub sets: *const Vec, } impl<'a> From<&'a SdpAttributeImageAttrSetList> for RustSdpAttributeImageAttrSetList { fn from(other: &SdpAttributeImageAttrSetList) -> Self { match other { &SdpAttributeImageAttrSetList::Wildcard => { RustSdpAttributeImageAttrSetList { sets: ptr::null() } } &SdpAttributeImageAttrSetList::Sets(ref sets) => { RustSdpAttributeImageAttrSetList { sets: sets } } } } } #[no_mangle] pub unsafe extern "C" fn sdp_imageattr_get_set_count( sets: *const Vec, ) -> size_t { (*sets).len() } #[no_mangle] pub unsafe extern "C" fn sdp_imageattr_get_sets( sets: *const Vec, ret_size: size_t, ret: *mut RustSdpAttributeImageAttrSet, ) { let rust_sets: Vec<_> = (*sets) .iter() .map(RustSdpAttributeImageAttrSet::from) .collect(); let sets = slice::from_raw_parts_mut(ret, ret_size); sets.clone_from_slice(rust_sets.as_slice()); } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeImageAttr { pub pt: u32, pub send: RustSdpAttributeImageAttrSetList, pub recv: RustSdpAttributeImageAttrSetList, } impl<'a> From<&'a SdpAttributeImageAttr> for RustSdpAttributeImageAttr { fn from(other: &SdpAttributeImageAttr) -> Self { RustSdpAttributeImageAttr { pt: match other.pt { SdpAttributePayloadType::Wildcard => u32::max_value(), SdpAttributePayloadType::PayloadType(x) => x as u32, }, send: RustSdpAttributeImageAttrSetList::from(&other.send), recv: RustSdpAttributeImageAttrSetList::from(&other.recv), } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_imageattr_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::ImageAttr) } #[no_mangle] pub unsafe extern "C" fn sdp_get_imageattrs( attributes: *const Vec, ret_size: size_t, ret_attrs: *mut RustSdpAttributeImageAttr, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::ImageAttr(ref data) = *x { Some(RustSdpAttributeImageAttr::from(data)) } else { None } }) .collect(); let imageattrs = slice::from_raw_parts_mut(ret_attrs, ret_size); imageattrs.copy_from_slice(attrs.as_slice()); } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeSctpmap { pub port: u32, pub channels: u32, } impl<'a> From<&'a SdpAttributeSctpmap> for RustSdpAttributeSctpmap { fn from(other: &SdpAttributeSctpmap) -> Self { RustSdpAttributeSctpmap { port: other.port as u32, channels: other.channels, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_sctpmap_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Sctpmap) } #[no_mangle] pub unsafe extern "C" fn sdp_get_sctpmaps( attributes: *const Vec, ret_size: size_t, ret_sctpmaps: *mut RustSdpAttributeSctpmap, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Sctpmap(ref data) = *x { Some(RustSdpAttributeSctpmap::from(data)) } else { None } }) .collect(); let sctpmaps = slice::from_raw_parts_mut(ret_sctpmaps, ret_size); sctpmaps.copy_from_slice(attrs.as_slice()); } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeSimulcastId { pub id: StringView, pub paused: bool, } impl<'a> From<&'a SdpAttributeSimulcastId> for RustSdpAttributeSimulcastId { fn from(other: &SdpAttributeSimulcastId) -> Self { RustSdpAttributeSimulcastId { id: StringView::from(other.id.as_str()), paused: other.paused, } } } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeSimulcastVersion { pub ids: *const Vec, } impl<'a> From<&'a SdpAttributeSimulcastVersion> for RustSdpAttributeSimulcastVersion { fn from(other: &SdpAttributeSimulcastVersion) -> Self { RustSdpAttributeSimulcastVersion { ids: &other.ids } } } #[no_mangle] pub unsafe extern "C" fn sdp_simulcast_get_ids_count( ids: *const Vec, ) -> size_t { (*ids).len() } #[no_mangle] pub unsafe extern "C" fn sdp_simulcast_get_ids( ids: *const Vec, ret_size: size_t, ret: *mut RustSdpAttributeSimulcastId, ) { let rust_ids: Vec<_> = (*ids) .iter() .map(RustSdpAttributeSimulcastId::from) .collect(); let ids = slice::from_raw_parts_mut(ret, ret_size); ids.clone_from_slice(rust_ids.as_slice()); } #[repr(C)] pub struct RustSdpAttributeSimulcast { pub send: *const Vec, pub receive: *const Vec, } impl<'a> From<&'a SdpAttributeSimulcast> for RustSdpAttributeSimulcast { fn from(other: &SdpAttributeSimulcast) -> Self { RustSdpAttributeSimulcast { send: &other.send, receive: &other.receive, } } } #[no_mangle] pub unsafe extern "C" fn sdp_simulcast_get_version_count( version_list: *const Vec, ) -> size_t { (*version_list).len() } #[no_mangle] pub unsafe extern "C" fn sdp_simulcast_get_versions( version_list: *const Vec, ret_size: size_t, ret: *mut RustSdpAttributeSimulcastVersion, ) { let rust_versions_list: Vec<_> = (*version_list) .iter() .map(RustSdpAttributeSimulcastVersion::from) .collect(); let versions = slice::from_raw_parts_mut(ret, ret_size); versions.clone_from_slice(rust_versions_list.as_slice()) } #[no_mangle] pub unsafe extern "C" fn sdp_get_simulcast( attributes: *const Vec, ret: *mut RustSdpAttributeSimulcast, ) -> nsresult { let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::Simulcast); if let Some(&SdpAttribute::Simulcast(ref data)) = attr { *ret = RustSdpAttributeSimulcast::from(data); return NS_OK; } NS_ERROR_INVALID_ARG } #[repr(C)] #[derive(Clone, Copy)] pub enum RustDirection { Recvonly, Sendonly, Sendrecv, Inactive, } impl<'a> From<&'a Option> for RustDirection { fn from(other: &Option) -> Self { match *other { Some(ref direction) => match *direction { SdpAttributeDirection::Recvonly => RustDirection::Recvonly, SdpAttributeDirection::Sendonly => RustDirection::Sendonly, SdpAttributeDirection::Sendrecv => RustDirection::Sendrecv, }, None => RustDirection::Inactive, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_direction(attributes: *const Vec) -> RustDirection { for attribute in (*attributes).iter() { match *attribute { SdpAttribute::Recvonly => { return RustDirection::Recvonly; } SdpAttribute::Sendonly => { return RustDirection::Sendonly; } SdpAttribute::Sendrecv => { return RustDirection::Sendrecv; } SdpAttribute::Inactive => { return RustDirection::Inactive; } _ => (), } } RustDirection::Sendrecv } #[repr(C)] pub struct RustSdpAttributeRemoteCandidate { pub component: u32, pub address: RustAddress, pub port: u32, } impl<'a> From<&'a SdpAttributeRemoteCandidate> for RustSdpAttributeRemoteCandidate { fn from(other: &SdpAttributeRemoteCandidate) -> Self { RustSdpAttributeRemoteCandidate { component: other.component, address: RustAddress::from(&other.address), port: other.port, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_remote_candidate_count( attributes: *const Vec, ) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::RemoteCandidate) } #[no_mangle] pub unsafe extern "C" fn sdp_get_remote_candidates( attributes: *const Vec, ret_size: size_t, ret_candidates: *mut RustSdpAttributeRemoteCandidate, ) { let attrs = (*attributes).iter().filter_map(|x| { if let SdpAttribute::RemoteCandidate(ref data) = *x { Some(RustSdpAttributeRemoteCandidate::from(data)) } else { None } }); let candidates = slice::from_raw_parts_mut(ret_candidates, ret_size); for (source, destination) in attrs.zip(candidates) { *destination = source } } #[no_mangle] pub unsafe extern "C" fn sdp_get_candidate_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Candidate) } #[no_mangle] pub unsafe extern "C" fn sdp_get_candidates( attributes: *const Vec, _ret_size: size_t, ret: *mut *const Vec, ) { let attr_strings: Vec = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Candidate(ref attr) = *x { // The serialized attribute starts with "candidate:...", this needs to be removed Some(attr.to_string()) } else { None } }) .collect(); *ret = Box::into_raw(Box::from(attr_strings)); } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeRidParameters { pub max_width: u32, pub max_height: u32, pub max_fps: u32, pub max_fs: u32, pub max_br: u32, pub max_pps: u32, pub unknown: *const Vec, } impl<'a> From<&'a SdpAttributeRidParameters> for RustSdpAttributeRidParameters { fn from(other: &SdpAttributeRidParameters) -> Self { RustSdpAttributeRidParameters { max_width: other.max_width, max_height: other.max_height, max_fps: other.max_fps, max_fs: other.max_fs, max_br: other.max_br, max_pps: other.max_pps, unknown: &other.unknown, } } } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeRid { pub id: StringView, pub direction: u32, pub formats: *const Vec, pub params: RustSdpAttributeRidParameters, pub depends: *const Vec, } impl<'a> From<&'a SdpAttributeRid> for RustSdpAttributeRid { fn from(other: &SdpAttributeRid) -> Self { RustSdpAttributeRid { id: StringView::from(other.id.as_str()), direction: other.direction.clone() as u32, formats: &other.formats, params: RustSdpAttributeRidParameters::from(&other.params), depends: &other.depends, } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_rid_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Rid) } #[no_mangle] pub unsafe extern "C" fn sdp_get_rids( attributes: *const Vec, ret_size: size_t, ret_rids: *mut RustSdpAttributeRid, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Rid(ref data) = *x { Some(RustSdpAttributeRid::from(data)) } else { None } }) .collect(); let rids = slice::from_raw_parts_mut(ret_rids, ret_size); rids.clone_from_slice(attrs.as_slice()); } #[repr(C)] #[derive(Clone, Copy)] pub struct RustSdpAttributeExtmap { pub id: u16, pub direction_specified: bool, pub direction: RustDirection, pub url: StringView, pub extension_attributes: StringView, } impl<'a> From<&'a SdpAttributeExtmap> for RustSdpAttributeExtmap { fn from(other: &SdpAttributeExtmap) -> Self { let dir = if other.direction.is_some() { RustDirection::from(&other.direction) } else { RustDirection::from(&Some(SdpAttributeDirection::Sendrecv)) }; RustSdpAttributeExtmap { id: other.id as u16, direction_specified: other.direction.is_some(), direction: dir, url: StringView::from(other.url.as_str()), extension_attributes: StringView::from(&other.extension_attributes), } } } #[no_mangle] pub unsafe extern "C" fn sdp_get_extmap_count(attributes: *const Vec) -> size_t { count_attribute((*attributes).as_slice(), SdpAttributeType::Extmap) } #[no_mangle] pub unsafe extern "C" fn sdp_get_extmaps( attributes: *const Vec, ret_size: size_t, ret_rids: *mut RustSdpAttributeExtmap, ) { let attrs: Vec<_> = (*attributes) .iter() .filter_map(|x| { if let SdpAttribute::Extmap(ref data) = *x { Some(RustSdpAttributeExtmap::from(data)) } else { None } }) .collect(); let extmaps = slice::from_raw_parts_mut(ret_rids, ret_size); extmaps.copy_from_slice(attrs.as_slice()); }