tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

attribute.rs (44061B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 use libc::{c_float, size_t};
      6 use std::ptr;
      7 use std::slice;
      8 
      9 use nserror::{nsresult, NS_ERROR_INVALID_ARG, NS_OK};
     10 use rsdparsa::attribute_type::*;
     11 use rsdparsa::SdpSession;
     12 
     13 use network::{RustAddress, RustExplicitlyTypedAddress};
     14 use types::StringView;
     15 
     16 #[no_mangle]
     17 pub unsafe extern "C" fn num_attributes(session: *const SdpSession) -> u32 {
     18    (*session).attribute.len() as u32
     19 }
     20 
     21 #[no_mangle]
     22 pub unsafe extern "C" fn get_attribute_ptr(
     23    session: *const SdpSession,
     24    index: u32,
     25    ret: *mut *const SdpAttribute,
     26 ) -> nsresult {
     27    match (&(*session).attribute).get(index as usize) {
     28        Some(attribute) => {
     29            *ret = attribute as *const SdpAttribute;
     30            NS_OK
     31        }
     32        None => NS_ERROR_INVALID_ARG,
     33    }
     34 }
     35 
     36 fn count_attribute(attributes: &[SdpAttribute], search: SdpAttributeType) -> usize {
     37    let mut count = 0;
     38    for attribute in (*attributes).iter() {
     39        if SdpAttributeType::from(attribute) == search {
     40            count += 1;
     41        }
     42    }
     43    count
     44 }
     45 
     46 fn argsearch(attributes: &[SdpAttribute], attribute_type: SdpAttributeType) -> Option<usize> {
     47    for (i, attribute) in (*attributes).iter().enumerate() {
     48        if SdpAttributeType::from(attribute) == attribute_type {
     49            return Some(i);
     50        }
     51    }
     52    None
     53 }
     54 
     55 pub unsafe fn has_attribute(
     56    attributes: *const Vec<SdpAttribute>,
     57    attribute_type: SdpAttributeType,
     58 ) -> bool {
     59    argsearch((*attributes).as_slice(), attribute_type).is_some()
     60 }
     61 
     62 fn get_attribute(
     63    attributes: &[SdpAttribute],
     64    attribute_type: SdpAttributeType,
     65 ) -> Option<&SdpAttribute> {
     66    argsearch(attributes, attribute_type).map(|i| &attributes[i])
     67 }
     68 
     69 #[repr(C)]
     70 #[derive(Clone, Copy)]
     71 pub enum RustSdpAttributeDtlsMessageType {
     72    Client,
     73    Server,
     74 }
     75 
     76 #[repr(C)]
     77 #[derive(Clone, Copy)]
     78 pub struct RustSdpAttributeDtlsMessage {
     79    pub role: u8,
     80    pub value: StringView,
     81 }
     82 
     83 impl<'a> From<&'a SdpAttributeDtlsMessage> for RustSdpAttributeDtlsMessage {
     84    fn from(other: &SdpAttributeDtlsMessage) -> Self {
     85        match other {
     86            &SdpAttributeDtlsMessage::Client(ref x) => RustSdpAttributeDtlsMessage {
     87                role: RustSdpAttributeDtlsMessageType::Client as u8,
     88                value: StringView::from(x.as_str()),
     89            },
     90            &SdpAttributeDtlsMessage::Server(ref x) => RustSdpAttributeDtlsMessage {
     91                role: RustSdpAttributeDtlsMessageType::Server as u8,
     92                value: StringView::from(x.as_str()),
     93            },
     94        }
     95    }
     96 }
     97 
     98 #[no_mangle]
     99 pub unsafe extern "C" fn sdp_get_dtls_message(
    100    attributes: *const Vec<SdpAttribute>,
    101    ret: *mut RustSdpAttributeDtlsMessage,
    102 ) -> nsresult {
    103    let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::DtlsMessage);
    104    if let Some(&SdpAttribute::DtlsMessage(ref dtls_message)) = attr {
    105        *ret = RustSdpAttributeDtlsMessage::from(dtls_message);
    106        return NS_OK;
    107    }
    108    NS_ERROR_INVALID_ARG
    109 }
    110 
    111 #[no_mangle]
    112 pub unsafe extern "C" fn sdp_get_iceufrag(
    113    attributes: *const Vec<SdpAttribute>,
    114    ret: *mut StringView,
    115 ) -> nsresult {
    116    let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::IceUfrag);
    117    if let Some(&SdpAttribute::IceUfrag(ref string)) = attr {
    118        *ret = StringView::from(string.as_str());
    119        return NS_OK;
    120    }
    121    NS_ERROR_INVALID_ARG
    122 }
    123 
    124 #[no_mangle]
    125 pub unsafe extern "C" fn sdp_get_icepwd(
    126    attributes: *const Vec<SdpAttribute>,
    127    ret: *mut StringView,
    128 ) -> nsresult {
    129    let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::IcePwd);
    130    if let Some(&SdpAttribute::IcePwd(ref string)) = attr {
    131        *ret = StringView::from(string.as_str());
    132        return NS_OK;
    133    }
    134    NS_ERROR_INVALID_ARG
    135 }
    136 
    137 #[no_mangle]
    138 pub unsafe extern "C" fn sdp_get_identity(
    139    attributes: *const Vec<SdpAttribute>,
    140    ret: *mut StringView,
    141 ) -> nsresult {
    142    let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::Identity);
    143    if let Some(&SdpAttribute::Identity(ref string)) = attr {
    144        *ret = StringView::from(string.as_str());
    145        return NS_OK;
    146    }
    147    NS_ERROR_INVALID_ARG
    148 }
    149 
    150 #[no_mangle]
    151 pub unsafe extern "C" fn sdp_get_iceoptions(
    152    attributes: *const Vec<SdpAttribute>,
    153    ret: *mut *const Vec<String>,
    154 ) -> nsresult {
    155    let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::IceOptions);
    156    if let Some(&SdpAttribute::IceOptions(ref options)) = attr {
    157        *ret = options;
    158        return NS_OK;
    159    }
    160    NS_ERROR_INVALID_ARG
    161 }
    162 
    163 #[no_mangle]
    164 pub unsafe extern "C" fn sdp_get_maxptime(
    165    attributes: *const Vec<SdpAttribute>,
    166    ret: *mut u64,
    167 ) -> nsresult {
    168    let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::MaxPtime);
    169    if let Some(&SdpAttribute::MaxPtime(ref max_ptime)) = attr {
    170        *ret = *max_ptime;
    171        return NS_OK;
    172    }
    173    NS_ERROR_INVALID_ARG
    174 }
    175 
    176 #[repr(C)]
    177 #[derive(Clone, Copy)]
    178 pub struct RustSdpAttributeFingerprint {
    179    hash_algorithm: u16,
    180    fingerprint: *const Vec<u8>,
    181 }
    182 
    183 impl<'a> From<&'a SdpAttributeFingerprint> for RustSdpAttributeFingerprint {
    184    fn from(other: &SdpAttributeFingerprint) -> Self {
    185        RustSdpAttributeFingerprint {
    186            hash_algorithm: other.hash_algorithm as u16,
    187            fingerprint: &other.fingerprint,
    188        }
    189    }
    190 }
    191 
    192 #[no_mangle]
    193 pub unsafe extern "C" fn sdp_get_fingerprint_count(attributes: *const Vec<SdpAttribute>) -> size_t {
    194    count_attribute((*attributes).as_slice(), SdpAttributeType::Fingerprint)
    195 }
    196 
    197 #[no_mangle]
    198 pub unsafe extern "C" fn sdp_get_fingerprints(
    199    attributes: *const Vec<SdpAttribute>,
    200    ret_size: size_t,
    201    ret_fingerprints: *mut RustSdpAttributeFingerprint,
    202 ) {
    203    let attrs: Vec<_> = (*attributes)
    204        .iter()
    205        .filter_map(|x| {
    206            if let SdpAttribute::Fingerprint(ref data) = *x {
    207                Some(RustSdpAttributeFingerprint::from(data))
    208            } else {
    209                None
    210            }
    211        })
    212        .collect();
    213    let fingerprints = slice::from_raw_parts_mut(ret_fingerprints, ret_size);
    214    fingerprints.copy_from_slice(attrs.as_slice());
    215 }
    216 
    217 #[repr(C)]
    218 #[derive(Clone)]
    219 pub enum RustSdpAttributeSetup {
    220    Active,
    221    Actpass,
    222    Holdconn,
    223    Passive,
    224 }
    225 
    226 impl<'a> From<&'a SdpAttributeSetup> for RustSdpAttributeSetup {
    227    fn from(other: &SdpAttributeSetup) -> Self {
    228        match *other {
    229            SdpAttributeSetup::Active => RustSdpAttributeSetup::Active,
    230            SdpAttributeSetup::Actpass => RustSdpAttributeSetup::Actpass,
    231            SdpAttributeSetup::Holdconn => RustSdpAttributeSetup::Holdconn,
    232            SdpAttributeSetup::Passive => RustSdpAttributeSetup::Passive,
    233        }
    234    }
    235 }
    236 
    237 #[no_mangle]
    238 pub unsafe extern "C" fn sdp_get_setup(
    239    attributes: *const Vec<SdpAttribute>,
    240    ret: *mut RustSdpAttributeSetup,
    241 ) -> nsresult {
    242    let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::Setup);
    243    if let Some(&SdpAttribute::Setup(ref setup)) = attr {
    244        *ret = RustSdpAttributeSetup::from(setup);
    245        return NS_OK;
    246    }
    247    NS_ERROR_INVALID_ARG
    248 }
    249 
    250 #[repr(C)]
    251 #[derive(Clone, Copy)]
    252 pub struct RustSdpAttributeSsrc {
    253    pub id: u32,
    254    pub attribute: StringView,
    255    pub value: StringView,
    256 }
    257 
    258 impl<'a> From<&'a SdpAttributeSsrc> for RustSdpAttributeSsrc {
    259    fn from(other: &SdpAttributeSsrc) -> Self {
    260        RustSdpAttributeSsrc {
    261            id: other.id,
    262            attribute: StringView::from(&other.attribute),
    263            value: StringView::from(&other.value),
    264        }
    265    }
    266 }
    267 
    268 #[no_mangle]
    269 pub unsafe extern "C" fn sdp_get_ssrc_count(attributes: *const Vec<SdpAttribute>) -> size_t {
    270    count_attribute((*attributes).as_slice(), SdpAttributeType::Ssrc)
    271 }
    272 
    273 #[no_mangle]
    274 pub unsafe extern "C" fn sdp_get_ssrcs(
    275    attributes: *const Vec<SdpAttribute>,
    276    ret_size: size_t,
    277    ret_ssrcs: *mut RustSdpAttributeSsrc,
    278 ) {
    279    let attrs: Vec<_> = (*attributes)
    280        .iter()
    281        .filter_map(|x| {
    282            if let SdpAttribute::Ssrc(ref data) = *x {
    283                Some(RustSdpAttributeSsrc::from(data))
    284            } else {
    285                None
    286            }
    287        })
    288        .collect();
    289    let ssrcs = slice::from_raw_parts_mut(ret_ssrcs, ret_size);
    290    ssrcs.copy_from_slice(attrs.as_slice());
    291 }
    292 
    293 #[repr(C)]
    294 #[derive(Clone, Copy)]
    295 pub enum RustSdpSsrcGroupSemantic {
    296    Duplication,
    297    FlowIdentification,
    298    ForwardErrorCorrection,
    299    ForwardErrorCorrectionFr,
    300    SIM,
    301 }
    302 
    303 impl<'a> From<&'a SdpSsrcGroupSemantic> for RustSdpSsrcGroupSemantic {
    304    fn from(other: &SdpSsrcGroupSemantic) -> Self {
    305        match *other {
    306            SdpSsrcGroupSemantic::Duplication => RustSdpSsrcGroupSemantic::Duplication,
    307            SdpSsrcGroupSemantic::FlowIdentification => {
    308                RustSdpSsrcGroupSemantic::FlowIdentification
    309            }
    310            SdpSsrcGroupSemantic::ForwardErrorCorrection => {
    311                RustSdpSsrcGroupSemantic::ForwardErrorCorrection
    312            }
    313            SdpSsrcGroupSemantic::ForwardErrorCorrectionFr => {
    314                RustSdpSsrcGroupSemantic::ForwardErrorCorrectionFr
    315            }
    316            SdpSsrcGroupSemantic::Sim => RustSdpSsrcGroupSemantic::SIM,
    317        }
    318    }
    319 }
    320 
    321 #[repr(C)]
    322 #[derive(Clone, Copy)]
    323 pub struct RustSdpSsrcGroup {
    324    pub semantic: RustSdpSsrcGroupSemantic,
    325    pub ssrcs: *const Vec<SdpAttributeSsrc>,
    326 }
    327 
    328 #[no_mangle]
    329 pub unsafe extern "C" fn sdp_get_ssrc_group_count(attributes: *const Vec<SdpAttribute>) -> size_t {
    330    count_attribute((*attributes).as_slice(), SdpAttributeType::SsrcGroup)
    331 }
    332 
    333 #[no_mangle]
    334 pub unsafe extern "C" fn sdp_get_ssrc_groups(
    335    attributes: *const Vec<SdpAttribute>,
    336    ret_size: size_t,
    337    ret_ssrc_groups: *mut RustSdpSsrcGroup,
    338 ) {
    339    let attrs: Vec<_> = (*attributes)
    340        .iter()
    341        .filter_map(|x| {
    342            if let SdpAttribute::SsrcGroup(ref semantic, ref ssrcs) = *x {
    343                Some(RustSdpSsrcGroup {
    344                    semantic: RustSdpSsrcGroupSemantic::from(semantic),
    345                    ssrcs: ssrcs,
    346                })
    347            } else {
    348                None
    349            }
    350        })
    351        .collect();
    352    let ssrc_groups = slice::from_raw_parts_mut(ret_ssrc_groups, ret_size);
    353    ssrc_groups.copy_from_slice(attrs.as_slice());
    354 }
    355 
    356 #[repr(C)]
    357 #[derive(Clone, Copy)]
    358 pub struct RustSdpAttributeRtpmap {
    359    pub payload_type: u8,
    360    pub codec_name: StringView,
    361    pub frequency: u32,
    362    pub channels: u32,
    363 }
    364 
    365 impl<'a> From<&'a SdpAttributeRtpmap> for RustSdpAttributeRtpmap {
    366    fn from(other: &SdpAttributeRtpmap) -> Self {
    367        RustSdpAttributeRtpmap {
    368            payload_type: other.payload_type as u8,
    369            codec_name: StringView::from(other.codec_name.as_str()),
    370            frequency: other.frequency as u32,
    371            channels: other.channels.unwrap_or(0),
    372        }
    373    }
    374 }
    375 
    376 #[no_mangle]
    377 pub unsafe extern "C" fn sdp_get_rtpmap_count(attributes: *const Vec<SdpAttribute>) -> size_t {
    378    count_attribute((*attributes).as_slice(), SdpAttributeType::Rtpmap)
    379 }
    380 
    381 #[no_mangle]
    382 pub unsafe extern "C" fn sdp_get_rtpmaps(
    383    attributes: *const Vec<SdpAttribute>,
    384    ret_size: size_t,
    385    ret_rtpmaps: *mut RustSdpAttributeRtpmap,
    386 ) {
    387    let attrs: Vec<_> = (*attributes)
    388        .iter()
    389        .filter_map(|x| {
    390            if let SdpAttribute::Rtpmap(ref data) = *x {
    391                Some(RustSdpAttributeRtpmap::from(data))
    392            } else {
    393                None
    394            }
    395        })
    396        .collect();
    397    let rtpmaps = slice::from_raw_parts_mut(ret_rtpmaps, ret_size);
    398    rtpmaps.copy_from_slice(attrs.as_slice());
    399 }
    400 
    401 #[repr(C)]
    402 #[derive(Clone, Copy)]
    403 pub struct RustRtxFmtpParameters {
    404    pub apt: u8,
    405    pub has_rtx_time: bool,
    406    pub rtx_time: u32,
    407 }
    408 
    409 #[repr(C)]
    410 #[derive(Clone, Copy)]
    411 pub struct RustAv1FmtpParameters {
    412    pub profile: u8,
    413    pub has_profile: bool,
    414    pub level_idx: u8,
    415    pub has_level_idx: bool,
    416    pub tier: u8,
    417    pub has_tier: bool,
    418 }
    419 
    420 #[repr(C)]
    421 #[derive(Clone, Copy)]
    422 pub struct RustSdpAttributeFmtpParameters {
    423    // H264
    424    pub packetization_mode: u32,
    425    pub level_asymmetry_allowed: bool,
    426    pub profile_level_id: u32,
    427    pub max_fs: u32,
    428    pub max_cpb: u32,
    429    pub max_dpb: u32,
    430    pub max_br: u32,
    431    pub max_mbps: u32,
    432 
    433    // VP8 and VP9
    434    // max_fs, already defined in H264
    435    pub max_fr: u32,
    436 
    437    // Opus
    438    pub maxplaybackrate: u32,
    439    pub maxaveragebitrate: u32,
    440    pub usedtx: bool,
    441    pub stereo: bool,
    442    pub useinbandfec: bool,
    443    pub cbr: bool,
    444    pub ptime: u32,
    445    pub minptime: u32,
    446    pub maxptime: u32,
    447 
    448    // telephone-event
    449    pub dtmf_tones: StringView,
    450 
    451    // AV1
    452    pub av1: RustAv1FmtpParameters,
    453 
    454    // RTX
    455    pub rtx: RustRtxFmtpParameters,
    456 
    457    // Red
    458    pub encodings: *const Vec<u8>,
    459 
    460    // Unknown
    461    pub unknown_tokens: *const Vec<String>,
    462 }
    463 
    464 impl<'a> From<&'a SdpAttributeFmtpParameters> for RustSdpAttributeFmtpParameters {
    465    fn from(other: &SdpAttributeFmtpParameters) -> Self {
    466        let rtx = if let Some(rtx) = other.rtx {
    467            RustRtxFmtpParameters {
    468                apt: rtx.apt,
    469                has_rtx_time: rtx.rtx_time.is_some(),
    470                rtx_time: rtx.rtx_time.unwrap_or(0),
    471            }
    472        } else {
    473            RustRtxFmtpParameters {
    474                apt: 0,
    475                has_rtx_time: false,
    476                rtx_time: 0,
    477            }
    478        };
    479        let av1 = RustAv1FmtpParameters {
    480            profile: other.profile.unwrap_or(0),
    481            has_profile: other.profile.is_some(),
    482            level_idx: other.level_idx.unwrap_or(0),
    483            has_level_idx: other.level_idx.is_some(),
    484            tier: other.tier.unwrap_or(0),
    485            has_tier: other.tier.is_some(),
    486        };
    487 
    488        RustSdpAttributeFmtpParameters {
    489            packetization_mode: other.packetization_mode,
    490            level_asymmetry_allowed: other.level_asymmetry_allowed,
    491            profile_level_id: other.profile_level_id,
    492            max_fs: other.max_fs,
    493            max_cpb: other.max_cpb,
    494            max_dpb: other.max_dpb,
    495            max_br: other.max_br,
    496            max_mbps: other.max_mbps,
    497            usedtx: other.usedtx,
    498            stereo: other.stereo,
    499            useinbandfec: other.useinbandfec,
    500            cbr: other.cbr,
    501            max_fr: other.max_fr,
    502            maxplaybackrate: other.maxplaybackrate,
    503            maxaveragebitrate: other.maxaveragebitrate,
    504            ptime: other.ptime,
    505            minptime: other.minptime,
    506            maxptime: other.maxptime,
    507            dtmf_tones: StringView::from(other.dtmf_tones.as_str()),
    508            av1,
    509            rtx,
    510            encodings: &other.encodings,
    511            unknown_tokens: &other.unknown_tokens,
    512        }
    513    }
    514 }
    515 
    516 #[repr(C)]
    517 #[derive(Clone, Copy)]
    518 pub struct RustSdpAttributeFmtp {
    519    pub payload_type: u8,
    520    pub codec_name: StringView,
    521    pub parameters: RustSdpAttributeFmtpParameters,
    522 }
    523 
    524 #[no_mangle]
    525 pub unsafe extern "C" fn sdp_get_fmtp_count(attributes: *const Vec<SdpAttribute>) -> size_t {
    526    count_attribute((*attributes).as_slice(), SdpAttributeType::Fmtp)
    527 }
    528 
    529 fn find_payload_type(attributes: &[SdpAttribute], payload_type: u8) -> Option<&SdpAttributeRtpmap> {
    530    attributes
    531        .iter()
    532        .filter_map(|x| {
    533            if let SdpAttribute::Rtpmap(ref data) = *x {
    534                if data.payload_type == payload_type {
    535                    Some(data)
    536                } else {
    537                    None
    538                }
    539            } else {
    540                None
    541            }
    542        })
    543        .next()
    544 }
    545 
    546 #[no_mangle]
    547 pub unsafe extern "C" fn sdp_get_fmtp(
    548    attributes: *const Vec<SdpAttribute>,
    549    ret_size: size_t,
    550    ret_fmtp: *mut RustSdpAttributeFmtp,
    551 ) -> size_t {
    552    let fmtps = (*attributes).iter().filter_map(|x| {
    553        if let SdpAttribute::Fmtp(ref data) = *x {
    554            Some(data)
    555        } else {
    556            None
    557        }
    558    });
    559    let mut rust_fmtps = Vec::new();
    560    for fmtp in fmtps {
    561        if let Some(rtpmap) = find_payload_type((*attributes).as_slice(), fmtp.payload_type) {
    562            rust_fmtps.push(RustSdpAttributeFmtp {
    563                payload_type: fmtp.payload_type as u8,
    564                codec_name: StringView::from(rtpmap.codec_name.as_str()),
    565                parameters: RustSdpAttributeFmtpParameters::from(&fmtp.parameters),
    566            });
    567        }
    568    }
    569    let fmtps = if ret_size <= rust_fmtps.len() {
    570        slice::from_raw_parts_mut(ret_fmtp, ret_size)
    571    } else {
    572        slice::from_raw_parts_mut(ret_fmtp, rust_fmtps.len())
    573    };
    574    fmtps.copy_from_slice(rust_fmtps.as_slice());
    575    fmtps.len()
    576 }
    577 
    578 #[no_mangle]
    579 pub unsafe extern "C" fn sdp_get_ptime(attributes: *const Vec<SdpAttribute>) -> i64 {
    580    for attribute in (*attributes).iter() {
    581        if let SdpAttribute::Ptime(time) = *attribute {
    582            return time as i64;
    583        }
    584    }
    585    -1
    586 }
    587 
    588 #[no_mangle]
    589 pub unsafe extern "C" fn sdp_get_max_msg_size(attributes: *const Vec<SdpAttribute>) -> i64 {
    590    for attribute in (*attributes).iter() {
    591        if let SdpAttribute::MaxMessageSize(max_msg_size) = *attribute {
    592            return max_msg_size as i64;
    593        }
    594    }
    595    -1
    596 }
    597 
    598 #[no_mangle]
    599 pub unsafe extern "C" fn sdp_get_sctp_port(attributes: *const Vec<SdpAttribute>) -> i64 {
    600    for attribute in (*attributes).iter() {
    601        if let SdpAttribute::SctpPort(port) = *attribute {
    602            return port as i64;
    603        }
    604    }
    605    -1
    606 }
    607 
    608 #[repr(C)]
    609 #[derive(Clone, Copy)]
    610 pub struct RustSdpAttributeFlags {
    611    pub ice_lite: bool,
    612    pub rtcp_mux: bool,
    613    pub rtcp_rsize: bool,
    614    pub bundle_only: bool,
    615    pub end_of_candidates: bool,
    616    pub extmap_allow_mixed: bool,
    617 }
    618 
    619 #[no_mangle]
    620 pub unsafe extern "C" fn sdp_get_attribute_flags(
    621    attributes: *const Vec<SdpAttribute>,
    622 ) -> RustSdpAttributeFlags {
    623    let mut ret = RustSdpAttributeFlags {
    624        ice_lite: false,
    625        rtcp_mux: false,
    626        rtcp_rsize: false,
    627        bundle_only: false,
    628        end_of_candidates: false,
    629        extmap_allow_mixed: false,
    630    };
    631    for attribute in (*attributes).iter() {
    632        if let SdpAttribute::IceLite = *attribute {
    633            ret.ice_lite = true;
    634        } else if let SdpAttribute::RtcpMux = *attribute {
    635            ret.rtcp_mux = true;
    636        } else if let SdpAttribute::RtcpRsize = *attribute {
    637            ret.rtcp_rsize = true;
    638        } else if let SdpAttribute::BundleOnly = *attribute {
    639            ret.bundle_only = true;
    640        } else if let SdpAttribute::EndOfCandidates = *attribute {
    641            ret.end_of_candidates = true;
    642        } else if let SdpAttribute::ExtmapAllowMixed = *attribute {
    643            ret.extmap_allow_mixed = true;
    644        }
    645    }
    646    ret
    647 }
    648 
    649 #[no_mangle]
    650 pub unsafe extern "C" fn sdp_get_mid(
    651    attributes: *const Vec<SdpAttribute>,
    652    ret: *mut StringView,
    653 ) -> nsresult {
    654    for attribute in (*attributes).iter() {
    655        if let SdpAttribute::Mid(ref data) = *attribute {
    656            *ret = StringView::from(data.as_str());
    657            return NS_OK;
    658        }
    659    }
    660    NS_ERROR_INVALID_ARG
    661 }
    662 
    663 #[repr(C)]
    664 #[derive(Clone, Copy)]
    665 pub struct RustSdpAttributeMsid {
    666    id: StringView,
    667    appdata: StringView,
    668 }
    669 
    670 impl<'a> From<&'a SdpAttributeMsid> for RustSdpAttributeMsid {
    671    fn from(other: &SdpAttributeMsid) -> Self {
    672        RustSdpAttributeMsid {
    673            id: StringView::from(other.id.as_str()),
    674            appdata: StringView::from(&other.appdata),
    675        }
    676    }
    677 }
    678 
    679 #[no_mangle]
    680 pub unsafe extern "C" fn sdp_get_msid_count(attributes: *const Vec<SdpAttribute>) -> size_t {
    681    count_attribute((*attributes).as_slice(), SdpAttributeType::Msid)
    682 }
    683 
    684 #[no_mangle]
    685 pub unsafe extern "C" fn sdp_get_msids(
    686    attributes: *const Vec<SdpAttribute>,
    687    ret_size: size_t,
    688    ret_msids: *mut RustSdpAttributeMsid,
    689 ) {
    690    let attrs: Vec<_> = (*attributes)
    691        .iter()
    692        .filter_map(|x| {
    693            if let SdpAttribute::Msid(ref data) = *x {
    694                Some(RustSdpAttributeMsid::from(data))
    695            } else {
    696                None
    697            }
    698        })
    699        .collect();
    700    let msids = slice::from_raw_parts_mut(ret_msids, ret_size);
    701    msids.copy_from_slice(attrs.as_slice());
    702 }
    703 
    704 // TODO: Finish msid attributes once parsing is changed upstream.
    705 #[repr(C)]
    706 #[derive(Clone, Copy)]
    707 pub struct RustSdpAttributeMsidSemantic {
    708    pub semantic: StringView,
    709    pub msids: *const Vec<String>,
    710 }
    711 
    712 impl<'a> From<&'a SdpAttributeMsidSemantic> for RustSdpAttributeMsidSemantic {
    713    fn from(other: &SdpAttributeMsidSemantic) -> Self {
    714        RustSdpAttributeMsidSemantic {
    715            semantic: StringView::from(other.semantic.as_str()),
    716            msids: &other.msids,
    717        }
    718    }
    719 }
    720 
    721 #[no_mangle]
    722 pub unsafe extern "C" fn sdp_get_msid_semantic_count(
    723    attributes: *const Vec<SdpAttribute>,
    724 ) -> size_t {
    725    count_attribute((*attributes).as_slice(), SdpAttributeType::MsidSemantic)
    726 }
    727 
    728 #[no_mangle]
    729 pub unsafe extern "C" fn sdp_get_msid_semantics(
    730    attributes: *const Vec<SdpAttribute>,
    731    ret_size: size_t,
    732    ret_msid_semantics: *mut RustSdpAttributeMsidSemantic,
    733 ) {
    734    let attrs: Vec<_> = (*attributes)
    735        .iter()
    736        .filter_map(|x| {
    737            if let SdpAttribute::MsidSemantic(ref data) = *x {
    738                Some(RustSdpAttributeMsidSemantic::from(data))
    739            } else {
    740                None
    741            }
    742        })
    743        .collect();
    744    let msid_semantics = slice::from_raw_parts_mut(ret_msid_semantics, ret_size);
    745    msid_semantics.copy_from_slice(attrs.as_slice());
    746 }
    747 
    748 #[repr(C)]
    749 #[derive(Clone, Copy)]
    750 pub enum RustSdpAttributeGroupSemantic {
    751    LipSynchronization,
    752    FlowIdentification,
    753    SingleReservationFlow,
    754    AlternateNetworkAddressType,
    755    ForwardErrorCorrection,
    756    DecodingDependency,
    757    Bundle,
    758 }
    759 
    760 impl<'a> From<&'a SdpAttributeGroupSemantic> for RustSdpAttributeGroupSemantic {
    761    fn from(other: &SdpAttributeGroupSemantic) -> Self {
    762        match *other {
    763            SdpAttributeGroupSemantic::LipSynchronization => {
    764                RustSdpAttributeGroupSemantic::LipSynchronization
    765            }
    766            SdpAttributeGroupSemantic::FlowIdentification => {
    767                RustSdpAttributeGroupSemantic::FlowIdentification
    768            }
    769            SdpAttributeGroupSemantic::SingleReservationFlow => {
    770                RustSdpAttributeGroupSemantic::SingleReservationFlow
    771            }
    772            SdpAttributeGroupSemantic::AlternateNetworkAddressType => {
    773                RustSdpAttributeGroupSemantic::AlternateNetworkAddressType
    774            }
    775            SdpAttributeGroupSemantic::ForwardErrorCorrection => {
    776                RustSdpAttributeGroupSemantic::ForwardErrorCorrection
    777            }
    778            SdpAttributeGroupSemantic::DecodingDependency => {
    779                RustSdpAttributeGroupSemantic::DecodingDependency
    780            }
    781            SdpAttributeGroupSemantic::Bundle => RustSdpAttributeGroupSemantic::Bundle,
    782        }
    783    }
    784 }
    785 
    786 #[repr(C)]
    787 #[derive(Clone, Copy)]
    788 pub struct RustSdpAttributeGroup {
    789    pub semantic: RustSdpAttributeGroupSemantic,
    790    pub tags: *const Vec<String>,
    791 }
    792 
    793 impl<'a> From<&'a SdpAttributeGroup> for RustSdpAttributeGroup {
    794    fn from(other: &SdpAttributeGroup) -> Self {
    795        RustSdpAttributeGroup {
    796            semantic: RustSdpAttributeGroupSemantic::from(&other.semantics),
    797            tags: &other.tags,
    798        }
    799    }
    800 }
    801 
    802 #[no_mangle]
    803 pub unsafe extern "C" fn sdp_get_group_count(attributes: *const Vec<SdpAttribute>) -> size_t {
    804    count_attribute((*attributes).as_slice(), SdpAttributeType::Group)
    805 }
    806 
    807 #[no_mangle]
    808 pub unsafe extern "C" fn sdp_get_groups(
    809    attributes: *const Vec<SdpAttribute>,
    810    ret_size: size_t,
    811    ret_groups: *mut RustSdpAttributeGroup,
    812 ) {
    813    let attrs: Vec<_> = (*attributes)
    814        .iter()
    815        .filter_map(|x| {
    816            if let SdpAttribute::Group(ref data) = *x {
    817                Some(RustSdpAttributeGroup::from(data))
    818            } else {
    819                None
    820            }
    821        })
    822        .collect();
    823    let groups = slice::from_raw_parts_mut(ret_groups, ret_size);
    824    groups.copy_from_slice(attrs.as_slice());
    825 }
    826 
    827 #[repr(C)]
    828 pub struct RustSdpAttributeRtcp {
    829    pub port: u32,
    830    pub unicast_addr: RustExplicitlyTypedAddress,
    831    pub has_address: bool,
    832 }
    833 
    834 impl<'a> From<&'a SdpAttributeRtcp> for RustSdpAttributeRtcp {
    835    fn from(other: &SdpAttributeRtcp) -> Self {
    836        match other.unicast_addr {
    837            Some(ref address) => RustSdpAttributeRtcp {
    838                port: other.port as u32,
    839                unicast_addr: address.into(),
    840                has_address: true,
    841            },
    842            None => RustSdpAttributeRtcp {
    843                port: other.port as u32,
    844                unicast_addr: RustExplicitlyTypedAddress::default(),
    845                has_address: false,
    846            },
    847        }
    848    }
    849 }
    850 
    851 #[no_mangle]
    852 pub unsafe extern "C" fn sdp_get_rtcp(
    853    attributes: *const Vec<SdpAttribute>,
    854    ret: *mut RustSdpAttributeRtcp,
    855 ) -> nsresult {
    856    let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::Rtcp);
    857    if let Some(&SdpAttribute::Rtcp(ref data)) = attr {
    858        *ret = RustSdpAttributeRtcp::from(data);
    859        return NS_OK;
    860    }
    861    NS_ERROR_INVALID_ARG
    862 }
    863 
    864 #[repr(C)]
    865 #[derive(Clone, Copy)]
    866 pub struct RustSdpAttributeRtcpFb {
    867    pub payload_type: u32,
    868    pub feedback_type: u32,
    869    pub parameter: StringView,
    870    pub extra: StringView,
    871 }
    872 
    873 impl<'a> From<&'a SdpAttributeRtcpFb> for RustSdpAttributeRtcpFb {
    874    fn from(other: &SdpAttributeRtcpFb) -> Self {
    875        RustSdpAttributeRtcpFb {
    876            payload_type: match other.payload_type {
    877                SdpAttributePayloadType::Wildcard => u32::max_value(),
    878                SdpAttributePayloadType::PayloadType(x) => x as u32,
    879            },
    880            feedback_type: other.feedback_type.clone() as u32,
    881            parameter: StringView::from(other.parameter.as_str()),
    882            extra: StringView::from(other.extra.as_str()),
    883        }
    884    }
    885 }
    886 
    887 #[no_mangle]
    888 pub unsafe extern "C" fn sdp_get_rtcpfb_count(attributes: *const Vec<SdpAttribute>) -> size_t {
    889    count_attribute((*attributes).as_slice(), SdpAttributeType::Rtcpfb)
    890 }
    891 
    892 #[no_mangle]
    893 pub unsafe extern "C" fn sdp_get_rtcpfbs(
    894    attributes: *const Vec<SdpAttribute>,
    895    ret_size: size_t,
    896    ret_rtcpfbs: *mut RustSdpAttributeRtcpFb,
    897 ) {
    898    let attrs: Vec<_> = (*attributes)
    899        .iter()
    900        .filter_map(|x| {
    901            if let SdpAttribute::Rtcpfb(ref data) = *x {
    902                Some(RustSdpAttributeRtcpFb::from(data))
    903            } else {
    904                None
    905            }
    906        })
    907        .collect();
    908    let rtcpfbs = slice::from_raw_parts_mut(ret_rtcpfbs, ret_size);
    909    rtcpfbs.clone_from_slice(attrs.as_slice());
    910 }
    911 
    912 #[repr(C)]
    913 #[derive(Clone, Copy)]
    914 pub struct RustSdpAttributeImageAttrXyRange {
    915    // range
    916    pub min: u32,
    917    pub max: u32,
    918    pub step: u32,
    919 
    920    // discrete values
    921    pub discrete_values: *const Vec<u32>,
    922 }
    923 
    924 impl<'a> From<&'a SdpAttributeImageAttrXyRange> for RustSdpAttributeImageAttrXyRange {
    925    fn from(other: &SdpAttributeImageAttrXyRange) -> Self {
    926        match other {
    927            &SdpAttributeImageAttrXyRange::Range(min, max, step) => {
    928                RustSdpAttributeImageAttrXyRange {
    929                    min,
    930                    max,
    931                    step: step.unwrap_or(1),
    932                    discrete_values: ptr::null(),
    933                }
    934            }
    935            &SdpAttributeImageAttrXyRange::DiscreteValues(ref discrete_values) => {
    936                RustSdpAttributeImageAttrXyRange {
    937                    min: 0,
    938                    max: 1,
    939                    step: 1,
    940                    discrete_values,
    941                }
    942            }
    943        }
    944    }
    945 }
    946 
    947 #[repr(C)]
    948 #[derive(Clone, Copy)]
    949 pub struct RustSdpAttributeImageAttrSRange {
    950    // range
    951    pub min: c_float,
    952    pub max: c_float,
    953 
    954    // discrete values
    955    pub discrete_values: *const Vec<c_float>,
    956 }
    957 
    958 impl<'a> From<&'a SdpAttributeImageAttrSRange> for RustSdpAttributeImageAttrSRange {
    959    fn from(other: &SdpAttributeImageAttrSRange) -> Self {
    960        match other {
    961            &SdpAttributeImageAttrSRange::Range(min, max) => RustSdpAttributeImageAttrSRange {
    962                min,
    963                max,
    964                discrete_values: ptr::null(),
    965            },
    966            &SdpAttributeImageAttrSRange::DiscreteValues(ref discrete_values) => {
    967                RustSdpAttributeImageAttrSRange {
    968                    min: 0.0,
    969                    max: 1.0,
    970                    discrete_values,
    971                }
    972            }
    973        }
    974    }
    975 }
    976 
    977 #[repr(C)]
    978 #[derive(Clone, Copy)]
    979 pub struct RustSdpAttributeImageAttrPRange {
    980    pub min: c_float,
    981    pub max: c_float,
    982 }
    983 
    984 impl<'a> From<&'a SdpAttributeImageAttrPRange> for RustSdpAttributeImageAttrPRange {
    985    fn from(other: &SdpAttributeImageAttrPRange) -> Self {
    986        RustSdpAttributeImageAttrPRange {
    987            min: other.min,
    988            max: other.max,
    989        }
    990    }
    991 }
    992 
    993 #[repr(C)]
    994 #[derive(Clone, Copy)]
    995 pub struct RustSdpAttributeImageAttrSet {
    996    pub x: RustSdpAttributeImageAttrXyRange,
    997    pub y: RustSdpAttributeImageAttrXyRange,
    998 
    999    pub has_sar: bool,
   1000    pub sar: RustSdpAttributeImageAttrSRange,
   1001 
   1002    pub has_par: bool,
   1003    pub par: RustSdpAttributeImageAttrPRange,
   1004 
   1005    pub q: c_float,
   1006 }
   1007 
   1008 impl<'a> From<&'a SdpAttributeImageAttrSet> for RustSdpAttributeImageAttrSet {
   1009    fn from(other: &SdpAttributeImageAttrSet) -> Self {
   1010        RustSdpAttributeImageAttrSet {
   1011            x: RustSdpAttributeImageAttrXyRange::from(&other.x),
   1012            y: RustSdpAttributeImageAttrXyRange::from(&other.y),
   1013 
   1014            has_sar: other.sar.is_some(),
   1015            sar: match other.sar {
   1016                Some(ref x) => RustSdpAttributeImageAttrSRange::from(x),
   1017                // This is just any valid value accepted by rust,
   1018                // it might as well by uninitilized
   1019                None => RustSdpAttributeImageAttrSRange::from(
   1020                    &SdpAttributeImageAttrSRange::DiscreteValues(vec![]),
   1021                ),
   1022            },
   1023 
   1024            has_par: other.par.is_some(),
   1025            par: match other.par {
   1026                Some(ref x) => RustSdpAttributeImageAttrPRange::from(x),
   1027                // This is just any valid value accepted by rust,
   1028                // it might as well by uninitilized
   1029                None => RustSdpAttributeImageAttrPRange { min: 0.0, max: 1.0 },
   1030            },
   1031 
   1032            q: other.q.unwrap_or(0.5),
   1033        }
   1034    }
   1035 }
   1036 
   1037 #[repr(C)]
   1038 #[derive(Clone, Copy)]
   1039 pub struct RustSdpAttributeImageAttrSetList {
   1040    pub sets: *const Vec<SdpAttributeImageAttrSet>,
   1041 }
   1042 
   1043 impl<'a> From<&'a SdpAttributeImageAttrSetList> for RustSdpAttributeImageAttrSetList {
   1044    fn from(other: &SdpAttributeImageAttrSetList) -> Self {
   1045        match other {
   1046            &SdpAttributeImageAttrSetList::Wildcard => {
   1047                RustSdpAttributeImageAttrSetList { sets: ptr::null() }
   1048            }
   1049            &SdpAttributeImageAttrSetList::Sets(ref sets) => {
   1050                RustSdpAttributeImageAttrSetList { sets: sets }
   1051            }
   1052        }
   1053    }
   1054 }
   1055 
   1056 #[no_mangle]
   1057 pub unsafe extern "C" fn sdp_imageattr_get_set_count(
   1058    sets: *const Vec<SdpAttributeImageAttrSet>,
   1059 ) -> size_t {
   1060    (*sets).len()
   1061 }
   1062 
   1063 #[no_mangle]
   1064 pub unsafe extern "C" fn sdp_imageattr_get_sets(
   1065    sets: *const Vec<SdpAttributeImageAttrSet>,
   1066    ret_size: size_t,
   1067    ret: *mut RustSdpAttributeImageAttrSet,
   1068 ) {
   1069    let rust_sets: Vec<_> = (*sets)
   1070        .iter()
   1071        .map(RustSdpAttributeImageAttrSet::from)
   1072        .collect();
   1073    let sets = slice::from_raw_parts_mut(ret, ret_size);
   1074    sets.clone_from_slice(rust_sets.as_slice());
   1075 }
   1076 
   1077 #[repr(C)]
   1078 #[derive(Clone, Copy)]
   1079 pub struct RustSdpAttributeImageAttr {
   1080    pub pt: u32,
   1081    pub send: RustSdpAttributeImageAttrSetList,
   1082    pub recv: RustSdpAttributeImageAttrSetList,
   1083 }
   1084 
   1085 impl<'a> From<&'a SdpAttributeImageAttr> for RustSdpAttributeImageAttr {
   1086    fn from(other: &SdpAttributeImageAttr) -> Self {
   1087        RustSdpAttributeImageAttr {
   1088            pt: match other.pt {
   1089                SdpAttributePayloadType::Wildcard => u32::max_value(),
   1090                SdpAttributePayloadType::PayloadType(x) => x as u32,
   1091            },
   1092            send: RustSdpAttributeImageAttrSetList::from(&other.send),
   1093            recv: RustSdpAttributeImageAttrSetList::from(&other.recv),
   1094        }
   1095    }
   1096 }
   1097 
   1098 #[no_mangle]
   1099 pub unsafe extern "C" fn sdp_get_imageattr_count(attributes: *const Vec<SdpAttribute>) -> size_t {
   1100    count_attribute((*attributes).as_slice(), SdpAttributeType::ImageAttr)
   1101 }
   1102 
   1103 #[no_mangle]
   1104 pub unsafe extern "C" fn sdp_get_imageattrs(
   1105    attributes: *const Vec<SdpAttribute>,
   1106    ret_size: size_t,
   1107    ret_attrs: *mut RustSdpAttributeImageAttr,
   1108 ) {
   1109    let attrs: Vec<_> = (*attributes)
   1110        .iter()
   1111        .filter_map(|x| {
   1112            if let SdpAttribute::ImageAttr(ref data) = *x {
   1113                Some(RustSdpAttributeImageAttr::from(data))
   1114            } else {
   1115                None
   1116            }
   1117        })
   1118        .collect();
   1119    let imageattrs = slice::from_raw_parts_mut(ret_attrs, ret_size);
   1120    imageattrs.copy_from_slice(attrs.as_slice());
   1121 }
   1122 
   1123 #[repr(C)]
   1124 #[derive(Clone, Copy)]
   1125 pub struct RustSdpAttributeSctpmap {
   1126    pub port: u32,
   1127    pub channels: u32,
   1128 }
   1129 
   1130 impl<'a> From<&'a SdpAttributeSctpmap> for RustSdpAttributeSctpmap {
   1131    fn from(other: &SdpAttributeSctpmap) -> Self {
   1132        RustSdpAttributeSctpmap {
   1133            port: other.port as u32,
   1134            channels: other.channels,
   1135        }
   1136    }
   1137 }
   1138 
   1139 #[no_mangle]
   1140 pub unsafe extern "C" fn sdp_get_sctpmap_count(attributes: *const Vec<SdpAttribute>) -> size_t {
   1141    count_attribute((*attributes).as_slice(), SdpAttributeType::Sctpmap)
   1142 }
   1143 
   1144 #[no_mangle]
   1145 pub unsafe extern "C" fn sdp_get_sctpmaps(
   1146    attributes: *const Vec<SdpAttribute>,
   1147    ret_size: size_t,
   1148    ret_sctpmaps: *mut RustSdpAttributeSctpmap,
   1149 ) {
   1150    let attrs: Vec<_> = (*attributes)
   1151        .iter()
   1152        .filter_map(|x| {
   1153            if let SdpAttribute::Sctpmap(ref data) = *x {
   1154                Some(RustSdpAttributeSctpmap::from(data))
   1155            } else {
   1156                None
   1157            }
   1158        })
   1159        .collect();
   1160    let sctpmaps = slice::from_raw_parts_mut(ret_sctpmaps, ret_size);
   1161    sctpmaps.copy_from_slice(attrs.as_slice());
   1162 }
   1163 
   1164 #[repr(C)]
   1165 #[derive(Clone, Copy)]
   1166 pub struct RustSdpAttributeSimulcastId {
   1167    pub id: StringView,
   1168    pub paused: bool,
   1169 }
   1170 
   1171 impl<'a> From<&'a SdpAttributeSimulcastId> for RustSdpAttributeSimulcastId {
   1172    fn from(other: &SdpAttributeSimulcastId) -> Self {
   1173        RustSdpAttributeSimulcastId {
   1174            id: StringView::from(other.id.as_str()),
   1175            paused: other.paused,
   1176        }
   1177    }
   1178 }
   1179 
   1180 #[repr(C)]
   1181 #[derive(Clone, Copy)]
   1182 pub struct RustSdpAttributeSimulcastVersion {
   1183    pub ids: *const Vec<SdpAttributeSimulcastId>,
   1184 }
   1185 
   1186 impl<'a> From<&'a SdpAttributeSimulcastVersion> for RustSdpAttributeSimulcastVersion {
   1187    fn from(other: &SdpAttributeSimulcastVersion) -> Self {
   1188        RustSdpAttributeSimulcastVersion { ids: &other.ids }
   1189    }
   1190 }
   1191 
   1192 #[no_mangle]
   1193 pub unsafe extern "C" fn sdp_simulcast_get_ids_count(
   1194    ids: *const Vec<SdpAttributeSimulcastId>,
   1195 ) -> size_t {
   1196    (*ids).len()
   1197 }
   1198 
   1199 #[no_mangle]
   1200 pub unsafe extern "C" fn sdp_simulcast_get_ids(
   1201    ids: *const Vec<SdpAttributeSimulcastId>,
   1202    ret_size: size_t,
   1203    ret: *mut RustSdpAttributeSimulcastId,
   1204 ) {
   1205    let rust_ids: Vec<_> = (*ids)
   1206        .iter()
   1207        .map(RustSdpAttributeSimulcastId::from)
   1208        .collect();
   1209    let ids = slice::from_raw_parts_mut(ret, ret_size);
   1210    ids.clone_from_slice(rust_ids.as_slice());
   1211 }
   1212 
   1213 #[repr(C)]
   1214 pub struct RustSdpAttributeSimulcast {
   1215    pub send: *const Vec<SdpAttributeSimulcastVersion>,
   1216    pub receive: *const Vec<SdpAttributeSimulcastVersion>,
   1217 }
   1218 
   1219 impl<'a> From<&'a SdpAttributeSimulcast> for RustSdpAttributeSimulcast {
   1220    fn from(other: &SdpAttributeSimulcast) -> Self {
   1221        RustSdpAttributeSimulcast {
   1222            send: &other.send,
   1223            receive: &other.receive,
   1224        }
   1225    }
   1226 }
   1227 
   1228 #[no_mangle]
   1229 pub unsafe extern "C" fn sdp_simulcast_get_version_count(
   1230    version_list: *const Vec<SdpAttributeSimulcastVersion>,
   1231 ) -> size_t {
   1232    (*version_list).len()
   1233 }
   1234 
   1235 #[no_mangle]
   1236 pub unsafe extern "C" fn sdp_simulcast_get_versions(
   1237    version_list: *const Vec<SdpAttributeSimulcastVersion>,
   1238    ret_size: size_t,
   1239    ret: *mut RustSdpAttributeSimulcastVersion,
   1240 ) {
   1241    let rust_versions_list: Vec<_> = (*version_list)
   1242        .iter()
   1243        .map(RustSdpAttributeSimulcastVersion::from)
   1244        .collect();
   1245    let versions = slice::from_raw_parts_mut(ret, ret_size);
   1246    versions.clone_from_slice(rust_versions_list.as_slice())
   1247 }
   1248 
   1249 #[no_mangle]
   1250 pub unsafe extern "C" fn sdp_get_simulcast(
   1251    attributes: *const Vec<SdpAttribute>,
   1252    ret: *mut RustSdpAttributeSimulcast,
   1253 ) -> nsresult {
   1254    let attr = get_attribute((*attributes).as_slice(), SdpAttributeType::Simulcast);
   1255    if let Some(&SdpAttribute::Simulcast(ref data)) = attr {
   1256        *ret = RustSdpAttributeSimulcast::from(data);
   1257        return NS_OK;
   1258    }
   1259    NS_ERROR_INVALID_ARG
   1260 }
   1261 
   1262 #[repr(C)]
   1263 #[derive(Clone, Copy)]
   1264 pub enum RustDirection {
   1265    Recvonly,
   1266    Sendonly,
   1267    Sendrecv,
   1268    Inactive,
   1269 }
   1270 
   1271 impl<'a> From<&'a Option<SdpAttributeDirection>> for RustDirection {
   1272    fn from(other: &Option<SdpAttributeDirection>) -> Self {
   1273        match *other {
   1274            Some(ref direction) => match *direction {
   1275                SdpAttributeDirection::Recvonly => RustDirection::Recvonly,
   1276                SdpAttributeDirection::Sendonly => RustDirection::Sendonly,
   1277                SdpAttributeDirection::Sendrecv => RustDirection::Sendrecv,
   1278            },
   1279            None => RustDirection::Inactive,
   1280        }
   1281    }
   1282 }
   1283 
   1284 #[no_mangle]
   1285 pub unsafe extern "C" fn sdp_get_direction(attributes: *const Vec<SdpAttribute>) -> RustDirection {
   1286    for attribute in (*attributes).iter() {
   1287        match *attribute {
   1288            SdpAttribute::Recvonly => {
   1289                return RustDirection::Recvonly;
   1290            }
   1291            SdpAttribute::Sendonly => {
   1292                return RustDirection::Sendonly;
   1293            }
   1294            SdpAttribute::Sendrecv => {
   1295                return RustDirection::Sendrecv;
   1296            }
   1297            SdpAttribute::Inactive => {
   1298                return RustDirection::Inactive;
   1299            }
   1300            _ => (),
   1301        }
   1302    }
   1303    RustDirection::Sendrecv
   1304 }
   1305 
   1306 #[repr(C)]
   1307 pub struct RustSdpAttributeRemoteCandidate {
   1308    pub component: u32,
   1309    pub address: RustAddress,
   1310    pub port: u32,
   1311 }
   1312 
   1313 impl<'a> From<&'a SdpAttributeRemoteCandidate> for RustSdpAttributeRemoteCandidate {
   1314    fn from(other: &SdpAttributeRemoteCandidate) -> Self {
   1315        RustSdpAttributeRemoteCandidate {
   1316            component: other.component,
   1317            address: RustAddress::from(&other.address),
   1318            port: other.port,
   1319        }
   1320    }
   1321 }
   1322 
   1323 #[no_mangle]
   1324 pub unsafe extern "C" fn sdp_get_remote_candidate_count(
   1325    attributes: *const Vec<SdpAttribute>,
   1326 ) -> size_t {
   1327    count_attribute((*attributes).as_slice(), SdpAttributeType::RemoteCandidate)
   1328 }
   1329 
   1330 #[no_mangle]
   1331 pub unsafe extern "C" fn sdp_get_remote_candidates(
   1332    attributes: *const Vec<SdpAttribute>,
   1333    ret_size: size_t,
   1334    ret_candidates: *mut RustSdpAttributeRemoteCandidate,
   1335 ) {
   1336    let attrs = (*attributes).iter().filter_map(|x| {
   1337        if let SdpAttribute::RemoteCandidate(ref data) = *x {
   1338            Some(RustSdpAttributeRemoteCandidate::from(data))
   1339        } else {
   1340            None
   1341        }
   1342    });
   1343    let candidates = slice::from_raw_parts_mut(ret_candidates, ret_size);
   1344    for (source, destination) in attrs.zip(candidates) {
   1345        *destination = source
   1346    }
   1347 }
   1348 
   1349 #[no_mangle]
   1350 pub unsafe extern "C" fn sdp_get_candidate_count(attributes: *const Vec<SdpAttribute>) -> size_t {
   1351    count_attribute((*attributes).as_slice(), SdpAttributeType::Candidate)
   1352 }
   1353 
   1354 #[no_mangle]
   1355 pub unsafe extern "C" fn sdp_get_candidates(
   1356    attributes: *const Vec<SdpAttribute>,
   1357    _ret_size: size_t,
   1358    ret: *mut *const Vec<String>,
   1359 ) {
   1360    let attr_strings: Vec<String> = (*attributes)
   1361        .iter()
   1362        .filter_map(|x| {
   1363            if let SdpAttribute::Candidate(ref attr) = *x {
   1364                // The serialized attribute starts with "candidate:...", this needs to be removed
   1365                Some(attr.to_string())
   1366            } else {
   1367                None
   1368            }
   1369        })
   1370        .collect();
   1371 
   1372    *ret = Box::into_raw(Box::from(attr_strings));
   1373 }
   1374 
   1375 #[repr(C)]
   1376 #[derive(Clone, Copy)]
   1377 pub struct RustSdpAttributeRidParameters {
   1378    pub max_width: u32,
   1379    pub max_height: u32,
   1380    pub max_fps: u32,
   1381    pub max_fs: u32,
   1382    pub max_br: u32,
   1383    pub max_pps: u32,
   1384    pub unknown: *const Vec<String>,
   1385 }
   1386 
   1387 impl<'a> From<&'a SdpAttributeRidParameters> for RustSdpAttributeRidParameters {
   1388    fn from(other: &SdpAttributeRidParameters) -> Self {
   1389        RustSdpAttributeRidParameters {
   1390            max_width: other.max_width,
   1391            max_height: other.max_height,
   1392            max_fps: other.max_fps,
   1393            max_fs: other.max_fs,
   1394            max_br: other.max_br,
   1395            max_pps: other.max_pps,
   1396 
   1397            unknown: &other.unknown,
   1398        }
   1399    }
   1400 }
   1401 
   1402 #[repr(C)]
   1403 #[derive(Clone, Copy)]
   1404 pub struct RustSdpAttributeRid {
   1405    pub id: StringView,
   1406    pub direction: u32,
   1407    pub formats: *const Vec<u16>,
   1408    pub params: RustSdpAttributeRidParameters,
   1409    pub depends: *const Vec<String>,
   1410 }
   1411 
   1412 impl<'a> From<&'a SdpAttributeRid> for RustSdpAttributeRid {
   1413    fn from(other: &SdpAttributeRid) -> Self {
   1414        RustSdpAttributeRid {
   1415            id: StringView::from(other.id.as_str()),
   1416            direction: other.direction.clone() as u32,
   1417            formats: &other.formats,
   1418            params: RustSdpAttributeRidParameters::from(&other.params),
   1419            depends: &other.depends,
   1420        }
   1421    }
   1422 }
   1423 
   1424 #[no_mangle]
   1425 pub unsafe extern "C" fn sdp_get_rid_count(attributes: *const Vec<SdpAttribute>) -> size_t {
   1426    count_attribute((*attributes).as_slice(), SdpAttributeType::Rid)
   1427 }
   1428 
   1429 #[no_mangle]
   1430 pub unsafe extern "C" fn sdp_get_rids(
   1431    attributes: *const Vec<SdpAttribute>,
   1432    ret_size: size_t,
   1433    ret_rids: *mut RustSdpAttributeRid,
   1434 ) {
   1435    let attrs: Vec<_> = (*attributes)
   1436        .iter()
   1437        .filter_map(|x| {
   1438            if let SdpAttribute::Rid(ref data) = *x {
   1439                Some(RustSdpAttributeRid::from(data))
   1440            } else {
   1441                None
   1442            }
   1443        })
   1444        .collect();
   1445    let rids = slice::from_raw_parts_mut(ret_rids, ret_size);
   1446    rids.clone_from_slice(attrs.as_slice());
   1447 }
   1448 
   1449 #[repr(C)]
   1450 #[derive(Clone, Copy)]
   1451 pub struct RustSdpAttributeExtmap {
   1452    pub id: u16,
   1453    pub direction_specified: bool,
   1454    pub direction: RustDirection,
   1455    pub url: StringView,
   1456    pub extension_attributes: StringView,
   1457 }
   1458 
   1459 impl<'a> From<&'a SdpAttributeExtmap> for RustSdpAttributeExtmap {
   1460    fn from(other: &SdpAttributeExtmap) -> Self {
   1461        let dir = if other.direction.is_some() {
   1462            RustDirection::from(&other.direction)
   1463        } else {
   1464            RustDirection::from(&Some(SdpAttributeDirection::Sendrecv))
   1465        };
   1466        RustSdpAttributeExtmap {
   1467            id: other.id as u16,
   1468            direction_specified: other.direction.is_some(),
   1469            direction: dir,
   1470            url: StringView::from(other.url.as_str()),
   1471            extension_attributes: StringView::from(&other.extension_attributes),
   1472        }
   1473    }
   1474 }
   1475 
   1476 #[no_mangle]
   1477 pub unsafe extern "C" fn sdp_get_extmap_count(attributes: *const Vec<SdpAttribute>) -> size_t {
   1478    count_attribute((*attributes).as_slice(), SdpAttributeType::Extmap)
   1479 }
   1480 
   1481 #[no_mangle]
   1482 pub unsafe extern "C" fn sdp_get_extmaps(
   1483    attributes: *const Vec<SdpAttribute>,
   1484    ret_size: size_t,
   1485    ret_rids: *mut RustSdpAttributeExtmap,
   1486 ) {
   1487    let attrs: Vec<_> = (*attributes)
   1488        .iter()
   1489        .filter_map(|x| {
   1490            if let SdpAttribute::Extmap(ref data) = *x {
   1491                Some(RustSdpAttributeExtmap::from(data))
   1492            } else {
   1493                None
   1494            }
   1495        })
   1496        .collect();
   1497    let extmaps = slice::from_raw_parts_mut(ret_rids, ret_size);
   1498    extmaps.copy_from_slice(attrs.as_slice());
   1499 }