mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 06:45:42 +00:00
Bug 1379265 - Add C API for rsdparsa; r=rillian
MozReview-Commit-ID: FdhpTT5wzwI --HG-- extra : rebase_source : b1fd70e19346794f9309a49cda4a06ccfcd403aa
This commit is contained in:
parent
ad14285e30
commit
ccaf43a57e
11
media/webrtc/signaling/src/sdp/rsdparsa_capi/Cargo.toml
Normal file
11
media/webrtc/signaling/src/sdp/rsdparsa_capi/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "rsdparsa_capi"
|
||||
version = "0.1.0"
|
||||
authors = ["Paul Ellenbogen <pe5@cs.princeton.edu>",
|
||||
"Nils Ohlmeier <github@ohlmeier.org>"]
|
||||
|
||||
[dependencies]
|
||||
libc = "^0.2.0"
|
||||
log = "^0.3"
|
||||
rsdparsa = {version = "0.1.0", path = "../rsdparsa"}
|
||||
nserror = { path = "../../../../../../xpcom/rust/nserror" }
|
752
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs
Normal file
752
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs
Normal file
@ -0,0 +1,752 @@
|
||||
use std::slice;
|
||||
use libc::{size_t, uint8_t, uint16_t, uint32_t, int64_t};
|
||||
|
||||
use rsdparsa::SdpSession;
|
||||
use rsdparsa::attribute_type::{SdpAttribute, SdpAttributeFingerprint, SdpAttributeSetup, SdpAttributeSsrc, SdpAttributeRtpmap, SdpAttributeMsid, SdpAttributeMsidSemantic, SdpAttributeGroupSemantic, SdpAttributeGroup, SdpAttributeRtcp, SdpAttributeSctpmap, SdpAttributeRemoteCandidate, SdpAttributeExtmap, SdpAttributeDirection};
|
||||
use nserror::{nsresult, NS_OK, NS_ERROR_INVALID_ARG};
|
||||
|
||||
use types::StringView;
|
||||
use network::RustIpAddr;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum RustSdpAttributeType {
|
||||
BundleOnly,
|
||||
Candidate,
|
||||
EndOfCandidates,
|
||||
Extmap,
|
||||
Fingerprint,
|
||||
Fmtp,
|
||||
Group,
|
||||
IceLite,
|
||||
IceMismatch,
|
||||
IceOptions,
|
||||
IcePwd,
|
||||
IceUfrag,
|
||||
Identity,
|
||||
ImageAttr,
|
||||
Inactive,
|
||||
Label,
|
||||
MaxMessageSize,
|
||||
MaxPtime,
|
||||
Mid,
|
||||
Msid,
|
||||
MsidSemantic,
|
||||
Ptime,
|
||||
Rid,
|
||||
Recvonly,
|
||||
RemoteCandidate,
|
||||
Rtpmap,
|
||||
Rtcp,
|
||||
Rtcpfb,
|
||||
RtcpMux,
|
||||
RtcpRsize,
|
||||
Sctpmap,
|
||||
SctpPort,
|
||||
Sendonly,
|
||||
Sendrecv,
|
||||
Setup,
|
||||
Simulcast,
|
||||
Ssrc,
|
||||
SsrcGroup,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SdpAttribute> for RustSdpAttributeType {
|
||||
fn from(other: &SdpAttribute) -> Self {
|
||||
match *other {
|
||||
SdpAttribute::BundleOnly{..} => RustSdpAttributeType::BundleOnly,
|
||||
SdpAttribute::Candidate{..} => RustSdpAttributeType::Candidate,
|
||||
SdpAttribute::EndOfCandidates{..} => RustSdpAttributeType::EndOfCandidates,
|
||||
SdpAttribute::Extmap{..} => RustSdpAttributeType::Extmap,
|
||||
SdpAttribute::Fingerprint{..} => RustSdpAttributeType::Fingerprint,
|
||||
SdpAttribute::Fmtp{..} => RustSdpAttributeType::Fmtp,
|
||||
SdpAttribute::Group{..} => RustSdpAttributeType::Group,
|
||||
SdpAttribute::IceLite{..} => RustSdpAttributeType::IceLite,
|
||||
SdpAttribute::IceMismatch{..} => RustSdpAttributeType::IceMismatch,
|
||||
SdpAttribute::IceOptions{..} => RustSdpAttributeType::IceOptions,
|
||||
SdpAttribute::IcePwd{..} => RustSdpAttributeType::IcePwd,
|
||||
SdpAttribute::IceUfrag{..} => RustSdpAttributeType::IceUfrag,
|
||||
SdpAttribute::Identity{..} => RustSdpAttributeType::Identity,
|
||||
SdpAttribute::ImageAttr{..} => RustSdpAttributeType::ImageAttr,
|
||||
SdpAttribute::Inactive{..} => RustSdpAttributeType::Inactive,
|
||||
SdpAttribute::Label{..} => RustSdpAttributeType::Label,
|
||||
SdpAttribute::MaxMessageSize{..} => RustSdpAttributeType::MaxMessageSize,
|
||||
SdpAttribute::MaxPtime{..} => RustSdpAttributeType::MaxPtime,
|
||||
SdpAttribute::Mid{..} => RustSdpAttributeType::Mid,
|
||||
SdpAttribute::Msid{..} => RustSdpAttributeType::Msid,
|
||||
SdpAttribute::MsidSemantic{..} => RustSdpAttributeType::MsidSemantic,
|
||||
SdpAttribute::Ptime{..} => RustSdpAttributeType::Ptime,
|
||||
SdpAttribute::Rid{..} => RustSdpAttributeType::Rid,
|
||||
SdpAttribute::Recvonly{..} => RustSdpAttributeType::Recvonly,
|
||||
SdpAttribute::RemoteCandidate{..} => RustSdpAttributeType::RemoteCandidate,
|
||||
SdpAttribute::Rtcp{..} => RustSdpAttributeType::Rtcp,
|
||||
SdpAttribute::Rtcpfb{..} => RustSdpAttributeType::Rtcpfb,
|
||||
SdpAttribute::RtcpMux{..} => RustSdpAttributeType::RtcpMux,
|
||||
SdpAttribute::RtcpRsize{..} => RustSdpAttributeType::RtcpRsize,
|
||||
SdpAttribute::Rtpmap{..} => RustSdpAttributeType::Rtpmap,
|
||||
SdpAttribute::Sctpmap{..} => RustSdpAttributeType::Sctpmap,
|
||||
SdpAttribute::SctpPort{..} => RustSdpAttributeType::SctpPort,
|
||||
SdpAttribute::Sendonly{..} => RustSdpAttributeType::Sendonly,
|
||||
SdpAttribute::Sendrecv{..} => RustSdpAttributeType::Sendrecv,
|
||||
SdpAttribute::Setup{..} => RustSdpAttributeType::Setup,
|
||||
SdpAttribute::Simulcast{..} => RustSdpAttributeType::Simulcast,
|
||||
SdpAttribute::Ssrc{..} => RustSdpAttributeType::Ssrc,
|
||||
SdpAttribute::SsrcGroup{..} => RustSdpAttributeType::SsrcGroup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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: RustSdpAttributeType) -> usize {
|
||||
let mut count = 0;
|
||||
for attribute in (*attributes).iter() {
|
||||
if RustSdpAttributeType::from(attribute) == search {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
fn argsearch(attributes: &[SdpAttribute], attribute_type: RustSdpAttributeType) -> Option<usize> {
|
||||
for (i, attribute) in (*attributes).iter().enumerate() {
|
||||
if RustSdpAttributeType::from(attribute) == attribute_type {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub unsafe fn has_attribute(attributes: *const Vec<SdpAttribute>, attribute_type: RustSdpAttributeType) -> bool {
|
||||
argsearch((*attributes).as_slice(), attribute_type).is_some()
|
||||
}
|
||||
|
||||
fn get_attribute(attributes: &[SdpAttribute], attribute_type: RustSdpAttributeType) -> Option<&SdpAttribute> {
|
||||
argsearch(attributes, attribute_type).map(|i| &attributes[i])
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_iceufrag(attributes: *const Vec<SdpAttribute>, ret: *mut StringView) -> nsresult {
|
||||
let attr = get_attribute((*attributes).as_slice(), RustSdpAttributeType::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<SdpAttribute>, ret: *mut StringView) -> nsresult {
|
||||
let attr = get_attribute((*attributes).as_slice(), RustSdpAttributeType::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<SdpAttribute>, ret: *mut StringView) -> nsresult {
|
||||
let attr = get_attribute((*attributes).as_slice(), RustSdpAttributeType::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<SdpAttribute>, ret: *mut *const Vec<String>) -> nsresult {
|
||||
let attr = get_attribute((*attributes).as_slice(), RustSdpAttributeType::IceOptions);
|
||||
if let Some(&SdpAttribute::IceOptions(ref options)) = attr {
|
||||
*ret = options;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ERROR_INVALID_ARG
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RustSdpAttributeFingerprint {
|
||||
hash_algorithm: StringView,
|
||||
fingerprint: StringView
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SdpAttributeFingerprint> for RustSdpAttributeFingerprint {
|
||||
fn from(other: &SdpAttributeFingerprint) -> Self {
|
||||
RustSdpAttributeFingerprint {
|
||||
hash_algorithm: StringView::from(other.hash_algorithm.as_str()),
|
||||
fingerprint: StringView::from(other.fingerprint.as_str())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_fingerprint_count(attributes: *const Vec<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::Fingerprint)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_fingerprints(attributes: *const Vec<SdpAttribute>, 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<SdpAttribute>, ret: *mut RustSdpAttributeSetup) -> nsresult {
|
||||
let attr = get_attribute((*attributes).as_slice(), RustSdpAttributeType::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: uint32_t,
|
||||
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<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::Ssrc)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_ssrcs(attributes: *const Vec<SdpAttribute>, 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());
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct RustSdpAttributeRtpmap {
|
||||
pub payload_type: uint8_t,
|
||||
pub codec_name: StringView,
|
||||
pub frequency: uint32_t,
|
||||
pub channels: uint32_t,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SdpAttributeRtpmap> for RustSdpAttributeRtpmap {
|
||||
fn from(other: &SdpAttributeRtpmap) -> Self {
|
||||
RustSdpAttributeRtpmap {
|
||||
payload_type: other.payload_type as uint8_t,
|
||||
codec_name: StringView::from(other.codec_name.as_str()),
|
||||
frequency: other.frequency as uint32_t,
|
||||
channels: other.channels.unwrap_or(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_rtpmap_count(attributes: *const Vec<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::Rtpmap)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_rtpmaps(attributes: *const Vec<SdpAttribute>, 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 RustSdpAttributeFmtp {
|
||||
pub payload_type: uint8_t,
|
||||
pub codec_name: StringView,
|
||||
pub tokens: *const Vec<String>,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_fmtp_count(attributes: *const Vec<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::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<SdpAttribute>, 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()),
|
||||
tokens: &fmtp.tokens
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
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<SdpAttribute>) -> int64_t {
|
||||
for attribute in (*attributes).iter() {
|
||||
if let SdpAttribute::Ptime(time) = *attribute {
|
||||
return time as int64_t;
|
||||
}
|
||||
}
|
||||
-1
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RustSdpAttributeFlags {
|
||||
pub ice_lite: bool,
|
||||
pub rtcp_mux: bool,
|
||||
pub bundle_only: bool,
|
||||
pub end_of_candidates: bool
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_attribute_flags(attributes: *const Vec<SdpAttribute>) -> RustSdpAttributeFlags {
|
||||
let mut ret = RustSdpAttributeFlags {
|
||||
ice_lite: false,
|
||||
rtcp_mux: 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::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<SdpAttribute>, 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<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::Msid)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_msids(attributes: *const Vec<SdpAttribute>, 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<String>
|
||||
}
|
||||
|
||||
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<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::MsidSemantic)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_msid_semantics(attributes: *const Vec<SdpAttribute>, 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<String>
|
||||
}
|
||||
|
||||
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<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::Group)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_groups(attributes: *const Vec<SdpAttribute>, 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());
|
||||
}
|
||||
|
||||
pub struct RustSdpAttributeRtcp {
|
||||
pub port: uint32_t,
|
||||
pub unicast_addr: RustIpAddr,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SdpAttributeRtcp> for RustSdpAttributeRtcp {
|
||||
fn from(other: &SdpAttributeRtcp) -> Self {
|
||||
RustSdpAttributeRtcp {
|
||||
port: other.port as u32,
|
||||
unicast_addr: RustIpAddr::from(&other.unicast_addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_rtcp(attributes: *const Vec<SdpAttribute>, ret: *mut RustSdpAttributeRtcp) -> nsresult {
|
||||
let attr = get_attribute((*attributes).as_slice(), RustSdpAttributeType::Rtcp);
|
||||
if let Some(&SdpAttribute::Rtcp(ref data)) = attr {
|
||||
*ret = RustSdpAttributeRtcp::from(data);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ERROR_INVALID_ARG
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_imageattr_count(attributes: *const Vec<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::ImageAttr)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_imageattrs(attributes: *const Vec<SdpAttribute>, ret_size: size_t, ret_groups: *mut StringView) {
|
||||
let attrs: Vec<_> = (*attributes).iter().filter_map(|x| if let SdpAttribute::ImageAttr(ref string) = *x {
|
||||
Some(StringView::from(string.as_str()))
|
||||
} else {
|
||||
None
|
||||
}).collect();
|
||||
let imageattrs = slice::from_raw_parts_mut(ret_groups, ret_size);
|
||||
imageattrs.copy_from_slice(attrs.as_slice());
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RustSdpAttributeSctpmap {
|
||||
pub port: uint32_t,
|
||||
pub channels: uint32_t,
|
||||
}
|
||||
|
||||
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<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::Sctpmap)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_sctpmaps(attributes: *const Vec<SdpAttribute>, 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 enum RustDirection {
|
||||
Recvonly,
|
||||
Sendonly,
|
||||
Sendrecv,
|
||||
Inactive
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Option<SdpAttributeDirection>> for RustDirection {
|
||||
fn from(other: &Option<SdpAttributeDirection>) -> 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<SdpAttribute>) -> 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: uint32_t,
|
||||
pub address: RustIpAddr,
|
||||
pub port: uint32_t,
|
||||
}
|
||||
|
||||
|
||||
impl<'a> From<&'a SdpAttributeRemoteCandidate> for RustSdpAttributeRemoteCandidate {
|
||||
fn from(other: &SdpAttributeRemoteCandidate) -> Self {
|
||||
RustSdpAttributeRemoteCandidate {
|
||||
component: other.component,
|
||||
address: RustIpAddr::from(&other.address),
|
||||
port: other.port
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_remote_candidate_count(attributes: *const Vec<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::RemoteCandidate)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_remote_candidates(attributes: *const Vec<SdpAttribute>, 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_rid_count(attributes: *const Vec<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::Rid)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_rids(attributes: *const Vec<SdpAttribute>, ret_size: size_t, ret_rids: *mut StringView) {
|
||||
let attrs: Vec<_> = (*attributes).iter().filter_map(|x| if let SdpAttribute::Rid(ref string) = *x {
|
||||
Some(StringView::from(string.as_str()))
|
||||
} else {
|
||||
None
|
||||
}).collect();
|
||||
let rids = slice::from_raw_parts_mut(ret_rids, ret_size);
|
||||
rids.copy_from_slice(attrs.as_slice());
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RustSdpAttributeExtmap {
|
||||
pub id: uint16_t,
|
||||
pub direction: RustDirection,
|
||||
pub url: StringView,
|
||||
pub extension_attributes: StringView
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SdpAttributeExtmap> for RustSdpAttributeExtmap {
|
||||
fn from(other: &SdpAttributeExtmap) -> Self {
|
||||
RustSdpAttributeExtmap {
|
||||
id : other.id as uint16_t,
|
||||
direction: RustDirection::from(&other.direction),
|
||||
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<SdpAttribute>) -> size_t {
|
||||
count_attribute((*attributes).as_slice(), RustSdpAttributeType::Extmap)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_extmaps(attributes: *const Vec<SdpAttribute>, 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());
|
||||
}
|
190
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/lib.rs
Normal file
190
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/lib.rs
Normal file
@ -0,0 +1,190 @@
|
||||
extern crate rsdparsa;
|
||||
extern crate libc;
|
||||
#[macro_use] extern crate log;
|
||||
extern crate nserror;
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::{str, slice, ptr};
|
||||
use std::os::raw::c_char;
|
||||
use std::error::Error;
|
||||
|
||||
use libc::size_t;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use nserror::{nsresult, NS_OK, NS_ERROR_INVALID_ARG};
|
||||
use rsdparsa::{SdpTiming, SdpBandwidth, SdpSession};
|
||||
use rsdparsa::error::SdpParserError;
|
||||
use rsdparsa::attribute_type::SdpAttribute;
|
||||
|
||||
pub mod types;
|
||||
pub mod network;
|
||||
pub mod attribute;
|
||||
pub mod media_section;
|
||||
|
||||
pub use types::{StringView, NULL_STRING};
|
||||
use network::{RustSdpOrigin, origin_view_helper, RustSdpConnection,
|
||||
get_bandwidth};
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn parse_sdp(sdp: *const u8, length: u32,
|
||||
fail_on_warning: bool,
|
||||
session: *mut *const SdpSession,
|
||||
error: *mut *const SdpParserError) -> nsresult {
|
||||
// Bug 1433529 tracks fixing the TODOs in this function.
|
||||
// TODO: Do I need to add explicit lifetime here?
|
||||
// https://gankro.github.io/blah/only-in-rust/#honorable-mention-variance
|
||||
let sdp_slice: &[u8] = slice::from_raw_parts(sdp, length as usize);
|
||||
let sdp_c_str = match CStr::from_bytes_with_nul(sdp_slice) {
|
||||
Ok(string) => string,
|
||||
Err(_) => {
|
||||
*session = ptr::null();
|
||||
*error = ptr::null(); // TODO: Give more useful return value here
|
||||
debug!("Error converting string");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
};
|
||||
let sdp_buf: &[u8] = sdp_c_str.to_bytes();
|
||||
let sdp_str_slice: &str = match str::from_utf8(sdp_buf) {
|
||||
Ok(string) => string,
|
||||
Err(_) => {
|
||||
*session = ptr::null();
|
||||
*error = ptr::null(); // TODO: Give more useful return value here
|
||||
debug!("Error converting string to utf8");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
};
|
||||
let parser_result = rsdparsa::parse_sdp(sdp_str_slice, fail_on_warning);
|
||||
match parser_result {
|
||||
Ok(parsed) => {
|
||||
*session = Rc::into_raw(Rc::new(parsed));
|
||||
*error = ptr::null();
|
||||
NS_OK
|
||||
},
|
||||
Err(e) => {
|
||||
*session = ptr::null();
|
||||
debug!("{:?}", e);
|
||||
debug!("Error parsing SDP in rust: {}", e.description());
|
||||
*error = Box::into_raw(Box::new(e));
|
||||
NS_ERROR_INVALID_ARG
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_free_session(sdp_ptr: *mut SdpSession) {
|
||||
let sdp = Rc::from_raw(sdp_ptr);
|
||||
drop(sdp);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_new_reference(session: *mut SdpSession) -> *const SdpSession {
|
||||
let original = Rc::from_raw(session);
|
||||
let ret = Rc::into_raw(Rc::clone(&original));
|
||||
Rc::into_raw(original); // So the original reference doesn't get dropped
|
||||
ret
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_error_line_num(error: *mut SdpParserError) -> size_t {
|
||||
match *error {
|
||||
SdpParserError::Line {line_number, ..} |
|
||||
SdpParserError::Unsupported { line_number, ..} |
|
||||
SdpParserError::Sequence {line_number, ..} => line_number
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_error_message(error: *mut SdpParserError) -> StringView {
|
||||
StringView::from((*error).description())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_free_error(error: *mut SdpParserError) {
|
||||
let e = Box::from_raw(error);
|
||||
drop(e);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn get_version(session: *const SdpSession) -> u64 {
|
||||
(*session).get_version()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_origin(session: *const SdpSession) -> RustSdpOrigin {
|
||||
origin_view_helper((*session).get_origin())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn session_view(session: *const SdpSession) -> StringView {
|
||||
StringView::from((*session).get_session().as_str())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_session_has_connection(session: *const SdpSession) -> bool {
|
||||
(*session).connection.is_some()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_session_connection(session: *const SdpSession,
|
||||
connection: *mut RustSdpConnection) -> nsresult {
|
||||
match (*session).connection {
|
||||
Some(ref c) => {
|
||||
*connection = RustSdpConnection::from(c);
|
||||
NS_OK
|
||||
},
|
||||
None => NS_ERROR_INVALID_ARG
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct RustSdpTiming {
|
||||
pub start: u64,
|
||||
pub stop: u64,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SdpTiming> for RustSdpTiming {
|
||||
fn from(timing: &SdpTiming) -> Self {
|
||||
RustSdpTiming {start: timing.start, stop: timing.stop}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn has_timing(session: *const SdpSession) -> bool {
|
||||
(*session).timing.is_some()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn timing(session: *const SdpSession,
|
||||
timing: *mut RustSdpTiming) -> nsresult {
|
||||
match (*session).timing {
|
||||
Some(ref t) => {
|
||||
*timing = RustSdpTiming::from(t);
|
||||
NS_OK
|
||||
},
|
||||
None => NS_ERROR_INVALID_ARG
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_media_section_count(session: *const SdpSession) -> size_t {
|
||||
(*session).media.len()
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn get_sdp_bandwidth(session: *const SdpSession,
|
||||
bandwidth_type: *const c_char) -> u32 {
|
||||
get_bandwidth(&(*session).bandwidth, bandwidth_type)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_session_bandwidth_vec(session: *const SdpSession) -> *const Vec<SdpBandwidth> {
|
||||
&(*session).bandwidth
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn get_sdp_session_attributes(session: *const SdpSession) -> *const Vec<SdpAttribute> {
|
||||
&(*session).attribute
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
use std::ptr;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use libc::{size_t, uint32_t};
|
||||
|
||||
use nserror::{nsresult, NS_OK, NS_ERROR_INVALID_ARG};
|
||||
use rsdparsa::{SdpBandwidth, SdpSession};
|
||||
use rsdparsa::media_type::{SdpMedia, SdpMediaValue, SdpProtocolValue,
|
||||
SdpFormatList};
|
||||
use rsdparsa::attribute_type::SdpAttribute;
|
||||
|
||||
use network::{get_bandwidth, RustSdpConnection};
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_media_section(session: *const SdpSession,
|
||||
index: size_t) -> *const SdpMedia {
|
||||
return match (*session).media.get(index) {
|
||||
Some(m) => m,
|
||||
None => ptr::null()
|
||||
};
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum RustSdpMediaValue {
|
||||
Audio,
|
||||
Video,
|
||||
Application,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SdpMediaValue> for RustSdpMediaValue {
|
||||
fn from(val: &SdpMediaValue) -> Self {
|
||||
match *val {
|
||||
SdpMediaValue::Audio => RustSdpMediaValue::Audio,
|
||||
SdpMediaValue::Video => RustSdpMediaValue::Video,
|
||||
SdpMediaValue::Application => RustSdpMediaValue::Application
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_rust_get_media_type(sdp_media: *const SdpMedia) -> RustSdpMediaValue {
|
||||
RustSdpMediaValue::from((*sdp_media).get_type())
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum RustSdpProtocolValue {
|
||||
RtpSavpf,
|
||||
UdpTlsRtpSavpf,
|
||||
TcpTlsRtpSavpf,
|
||||
DtlsSctp,
|
||||
UdpDtlsSctp,
|
||||
TcpDtlsSctp,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SdpProtocolValue> for RustSdpProtocolValue {
|
||||
fn from(val: &SdpProtocolValue) -> Self {
|
||||
match *val {
|
||||
SdpProtocolValue::RtpSavpf => RustSdpProtocolValue::RtpSavpf,
|
||||
SdpProtocolValue::UdpTlsRtpSavpf => RustSdpProtocolValue::UdpTlsRtpSavpf,
|
||||
SdpProtocolValue::TcpTlsRtpSavpf => RustSdpProtocolValue::TcpTlsRtpSavpf,
|
||||
SdpProtocolValue::DtlsSctp => RustSdpProtocolValue::DtlsSctp,
|
||||
SdpProtocolValue::UdpDtlsSctp => RustSdpProtocolValue::UdpDtlsSctp,
|
||||
SdpProtocolValue::TcpDtlsSctp => RustSdpProtocolValue::TcpDtlsSctp,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_media_protocol(sdp_media: *const SdpMedia) -> RustSdpProtocolValue {
|
||||
RustSdpProtocolValue::from((*sdp_media).get_proto())
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum RustSdpFormatType {
|
||||
Integers,
|
||||
Strings
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_format_type(sdp_media: *const SdpMedia) -> RustSdpFormatType {
|
||||
match *(*sdp_media).get_formats() {
|
||||
SdpFormatList::Integers(_) => RustSdpFormatType::Integers,
|
||||
SdpFormatList::Strings(_) => RustSdpFormatType::Strings
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_format_string_vec(sdp_media: *const SdpMedia) -> *const Vec<String> {
|
||||
if let SdpFormatList::Strings(ref formats) = *(*sdp_media).get_formats() {
|
||||
formats
|
||||
} else {
|
||||
ptr::null()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_format_u32_vec(sdp_media: *const SdpMedia) -> *const Vec<u32> {
|
||||
if let SdpFormatList::Integers(ref formats) = *(*sdp_media).get_formats() {
|
||||
formats
|
||||
} else {
|
||||
ptr::null()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_media_port(sdp_media: *const SdpMedia) -> uint32_t {
|
||||
(*sdp_media).get_port()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_media_port_count(sdp_media: *const SdpMedia) -> uint32_t {
|
||||
(*sdp_media).get_port_count()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_media_bandwidth(sdp_media: *const SdpMedia,
|
||||
bandwidth_type: *const c_char) -> uint32_t {
|
||||
get_bandwidth((*sdp_media).get_bandwidth(), bandwidth_type)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_media_bandwidth_vec(sdp_media: *const SdpMedia) -> *const Vec<SdpBandwidth> {
|
||||
(*sdp_media).get_bandwidth()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_media_has_connection(sdp_media: *const SdpMedia) -> bool {
|
||||
(*sdp_media).has_connection()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_media_connection(sdp_media: *const SdpMedia, ret: *mut RustSdpConnection) -> nsresult {
|
||||
if let &Some(ref connection) = (*sdp_media).get_connection() {
|
||||
*ret = RustSdpConnection::from(connection);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ERROR_INVALID_ARG
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_get_media_attribute_list(sdp_media: *const SdpMedia) -> *const Vec<SdpAttribute> {
|
||||
(*sdp_media).get_attributes()
|
||||
}
|
180
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/network.rs
Normal file
180
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/network.rs
Normal file
@ -0,0 +1,180 @@
|
||||
use std::net::IpAddr;
|
||||
use std::os::raw::c_char;
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use libc::{uint8_t, uint64_t};
|
||||
|
||||
use rsdparsa::{SdpOrigin, SdpConnection, SdpBandwidth};
|
||||
|
||||
use types::StringView;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum RustSdpAddrType {
|
||||
None,
|
||||
IP4,
|
||||
IP6
|
||||
}
|
||||
|
||||
impl<'a> From<&'a IpAddr> for RustSdpAddrType {
|
||||
fn from(addr: &IpAddr) -> RustSdpAddrType {
|
||||
match *addr {
|
||||
IpAddr::V4(_) => RustSdpAddrType::IP4,
|
||||
IpAddr::V6(_) => RustSdpAddrType::IP6
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_octets(addr: &IpAddr) -> [u8; 16] {
|
||||
let mut octets = [0; 16];
|
||||
match *addr {
|
||||
IpAddr::V4(v4_addr) => {
|
||||
let v4_octets = v4_addr.octets();
|
||||
(&mut octets[0..4]).copy_from_slice(&v4_octets);
|
||||
},
|
||||
IpAddr::V6(v6_addr) => {
|
||||
let v6_octets = v6_addr.octets();
|
||||
octets.copy_from_slice(&v6_octets);
|
||||
}
|
||||
}
|
||||
octets
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RustIpAddr {
|
||||
addr_type: RustSdpAddrType,
|
||||
unicast_addr: [u8; 50]
|
||||
}
|
||||
|
||||
impl<'a> From<&'a IpAddr> for RustIpAddr {
|
||||
fn from(addr: &IpAddr) -> Self {
|
||||
let mut c_addr = [0; 50];
|
||||
let str_addr = format!("{}", addr);
|
||||
let str_bytes = str_addr.as_bytes();
|
||||
if str_bytes.len() < 50 {
|
||||
c_addr[..str_bytes.len()].copy_from_slice(&str_bytes);
|
||||
}
|
||||
RustIpAddr {addr_type: RustSdpAddrType::from(addr),
|
||||
unicast_addr: c_addr }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Option<IpAddr>> for RustIpAddr {
|
||||
fn from(addr: &Option<IpAddr>) -> Self {
|
||||
match *addr {
|
||||
Some(ref x) => RustIpAddr::from(x),
|
||||
None => RustIpAddr {
|
||||
addr_type: RustSdpAddrType::None,
|
||||
unicast_addr: [0; 50]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RustSdpConnection {
|
||||
pub addr: RustIpAddr,
|
||||
pub ttl: uint8_t,
|
||||
pub amount: uint64_t
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SdpConnection> for RustSdpConnection {
|
||||
fn from(sdp_connection: &SdpConnection) -> Self {
|
||||
let ttl = match sdp_connection.ttl {
|
||||
Some(x) => x as u8,
|
||||
None => 0
|
||||
};
|
||||
let amount = match sdp_connection.amount {
|
||||
Some(x) => x as u64,
|
||||
None => 0
|
||||
};
|
||||
RustSdpConnection { addr: RustIpAddr::from(&sdp_connection.addr),
|
||||
ttl: ttl, amount: amount }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RustSdpOrigin {
|
||||
username: StringView,
|
||||
session_id: u64,
|
||||
session_version: u64,
|
||||
addr: RustIpAddr,
|
||||
}
|
||||
|
||||
|
||||
fn bandwidth_match(str_bw: &str, enum_bw: &SdpBandwidth) -> bool {
|
||||
match *enum_bw {
|
||||
SdpBandwidth::As(_) => str_bw == "AS",
|
||||
SdpBandwidth::Ct(_) => str_bw == "CT",
|
||||
SdpBandwidth::Tias(_) => str_bw == "TIAS",
|
||||
SdpBandwidth::Unknown(ref type_name, _) => str_bw == type_name,
|
||||
}
|
||||
}
|
||||
|
||||
fn bandwidth_value(bandwidth: &SdpBandwidth) -> u32 {
|
||||
match *bandwidth {
|
||||
SdpBandwidth::As(x) | SdpBandwidth::Ct(x) |
|
||||
SdpBandwidth::Tias(x) => x,
|
||||
SdpBandwidth::Unknown(_, _) => 0
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn get_bandwidth(bandwidths: &Vec<SdpBandwidth>,
|
||||
bandwidth_type: *const c_char) -> u32 {
|
||||
let bw_type = match CStr::from_ptr(bandwidth_type).to_str() {
|
||||
Ok(string) => string,
|
||||
Err(_) => return 0
|
||||
};
|
||||
for bandwidth in bandwidths.iter() {
|
||||
if bandwidth_match(bw_type, bandwidth) {
|
||||
return bandwidth_value(bandwidth);
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_serialize_bandwidth(bw: *const Vec<SdpBandwidth>) -> *mut c_char {
|
||||
let mut builder = String::new();
|
||||
for bandwidth in (*bw).iter() {
|
||||
match *bandwidth {
|
||||
SdpBandwidth::As(val) => {
|
||||
builder.push_str("b=AS:");
|
||||
builder.push_str(&val.to_string());
|
||||
builder.push_str("\r\n");
|
||||
},
|
||||
SdpBandwidth::Ct(val) => {
|
||||
builder.push_str("b=CT:");
|
||||
builder.push_str(&val.to_string());
|
||||
builder.push_str("\r\n");
|
||||
},
|
||||
SdpBandwidth::Tias(val) => {
|
||||
builder.push_str("b=TIAS:");
|
||||
builder.push_str(&val.to_string());
|
||||
builder.push_str("\r\n");
|
||||
},
|
||||
SdpBandwidth::Unknown(ref name, val) => {
|
||||
builder.push_str("b=");
|
||||
builder.push_str(name.as_str());
|
||||
builder.push(':');
|
||||
builder.push_str(&val.to_string());
|
||||
builder.push_str("\r\n");
|
||||
},
|
||||
}
|
||||
}
|
||||
CString::from_vec_unchecked(builder.into_bytes()).into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sdp_free_string(s: *mut c_char) {
|
||||
drop(CString::from_raw(s));
|
||||
}
|
||||
|
||||
pub unsafe fn origin_view_helper(origin: &SdpOrigin) -> RustSdpOrigin {
|
||||
RustSdpOrigin {
|
||||
username: StringView::from(origin.username.as_str()),
|
||||
session_id: origin.session_id,
|
||||
session_version: origin.session_version,
|
||||
addr: RustIpAddr::from(&origin.unicast_addr)
|
||||
}
|
||||
}
|
65
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/types.rs
Normal file
65
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/types.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use libc::{size_t, uint32_t};
|
||||
|
||||
use nserror::{nsresult, NS_OK, NS_ERROR_INVALID_ARG};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct StringView {
|
||||
buffer: *const u8,
|
||||
len: size_t
|
||||
}
|
||||
|
||||
pub const NULL_STRING: StringView = StringView { buffer: 0 as *const u8,
|
||||
len: 0 };
|
||||
|
||||
impl<'a> From<&'a str> for StringView {
|
||||
fn from(input: &str) -> StringView {
|
||||
StringView { buffer: input.as_ptr(), len: input.len()}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: AsRef<str>> From<&'a Option<T>> for StringView {
|
||||
fn from(input: &Option<T>) -> StringView {
|
||||
match *input {
|
||||
Some(ref x) => StringView { buffer: x.as_ref().as_ptr(),
|
||||
len: x.as_ref().len()},
|
||||
None => NULL_STRING
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn string_vec_len(vec: *const Vec<String>) -> size_t {
|
||||
(*vec).len() as size_t
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn string_vec_get_view(vec: *const Vec<String>,
|
||||
index: size_t,
|
||||
ret: *mut StringView) -> nsresult {
|
||||
match (*vec).get(index) {
|
||||
Some(ref string) => {
|
||||
*ret = StringView::from(string.as_str());
|
||||
NS_OK
|
||||
},
|
||||
None => NS_ERROR_INVALID_ARG
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn u32_vec_len(vec: *const Vec<u32>) -> size_t {
|
||||
(*vec).len()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn u32_vec_get(vec: *const Vec<u32>,
|
||||
index: size_t,
|
||||
ret: *mut uint32_t) -> nsresult {
|
||||
match (*vec).get(index) {
|
||||
Some(val) => {
|
||||
*ret = *val;
|
||||
NS_OK
|
||||
},
|
||||
None => NS_ERROR_INVALID_ARG
|
||||
}
|
||||
}
|
15
toolkit/library/gtest/rust/Cargo.lock
generated
15
toolkit/library/gtest/rust/Cargo.lock
generated
@ -645,6 +645,7 @@ dependencies = [
|
||||
"nserror 0.1.0",
|
||||
"nsstring 0.1.0",
|
||||
"prefs_parser 0.0.1",
|
||||
"rsdparsa_capi 0.1.0",
|
||||
"rust_url_capi 0.0.1",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"u2fhid 0.1.0",
|
||||
@ -1219,6 +1220,20 @@ dependencies = [
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsdparsa"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "rsdparsa_capi"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nserror 0.1.0",
|
||||
"rsdparsa 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "runloop"
|
||||
version = "0.1.0"
|
||||
|
15
toolkit/library/rust/Cargo.lock
generated
15
toolkit/library/rust/Cargo.lock
generated
@ -643,6 +643,7 @@ dependencies = [
|
||||
"nserror 0.1.0",
|
||||
"nsstring 0.1.0",
|
||||
"prefs_parser 0.0.1",
|
||||
"rsdparsa_capi 0.1.0",
|
||||
"rust_url_capi 0.0.1",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"u2fhid 0.1.0",
|
||||
@ -1206,6 +1207,20 @@ dependencies = [
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsdparsa"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "rsdparsa_capi"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nserror 0.1.0",
|
||||
"rsdparsa 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "runloop"
|
||||
version = "0.1.0"
|
||||
|
@ -24,6 +24,7 @@ encoding_glue = { path = "../../../../intl/encoding_glue" }
|
||||
audioipc-client = { path = "../../../../media/audioipc/client", version = "0.2", optional = true }
|
||||
audioipc-server = { path = "../../../../media/audioipc/server", version = "0.2", optional = true }
|
||||
u2fhid = { path = "../../../../dom/webauthn/u2f-hid-rs" }
|
||||
rsdparsa_capi = { path = "../../../../media/webrtc/signaling/src/sdp/rsdparsa_capi" }
|
||||
# We have these to enforce common feature sets for said crates.
|
||||
log = {version = "0.3", features = ["release_max_level_info"]}
|
||||
syn = { version = "0.11", features = ["full", "visit", "parsing"] }
|
||||
|
@ -26,6 +26,7 @@ extern crate u2fhid;
|
||||
extern crate log;
|
||||
extern crate syn;
|
||||
extern crate cosec;
|
||||
extern crate rsdparsa_capi;
|
||||
|
||||
use std::boxed::Box;
|
||||
use std::ffi::CStr;
|
||||
|
Loading…
Reference in New Issue
Block a user