tor-browser

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

lib.rs (8550B)


      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 extern crate libc;
      6 extern crate nserror;
      7 extern crate rsdparsa;
      8 
      9 use std::ffi::CString;
     10 use std::os::raw::c_char;
     11 use std::ptr;
     12 
     13 use libc::size_t;
     14 
     15 use std::rc::Rc;
     16 
     17 use std::convert::{TryFrom, TryInto};
     18 
     19 use nserror::{nsresult, NS_ERROR_INVALID_ARG, NS_OK};
     20 use rsdparsa::address::ExplicitlyTypedAddress;
     21 use rsdparsa::anonymizer::{AnonymizingClone, StatefulSdpAnonymizer};
     22 use rsdparsa::attribute_type::SdpAttribute;
     23 use rsdparsa::error::SdpParserError;
     24 use rsdparsa::media_type::{SdpMediaValue, SdpProtocolValue};
     25 use rsdparsa::{SdpBandwidth, SdpSession, SdpTiming};
     26 
     27 #[macro_use]
     28 extern crate log;
     29 
     30 pub mod attribute;
     31 pub mod media_section;
     32 pub mod network;
     33 pub mod types;
     34 
     35 use network::{
     36    get_bandwidth, origin_view_helper, RustAddressType, RustSdpConnection, RustSdpOrigin,
     37 };
     38 pub use types::{StringView, NULL_STRING};
     39 
     40 #[no_mangle]
     41 pub unsafe extern "C" fn parse_sdp(
     42    sdp: StringView,
     43    fail_on_warning: bool,
     44    session: *mut *const SdpSession,
     45    parser_error: *mut *const SdpParserError,
     46 ) -> nsresult {
     47    let sdp_str: String = match sdp.try_into() {
     48        Ok(string) => string,
     49        Err(boxed_error) => {
     50            *session = ptr::null();
     51            *parser_error = Box::into_raw(Box::new(SdpParserError::Sequence {
     52                message: format!("{}", boxed_error),
     53                line_number: 0,
     54            }));
     55            return NS_ERROR_INVALID_ARG;
     56        }
     57    };
     58 
     59    let parser_result = rsdparsa::parse_sdp(&sdp_str, fail_on_warning);
     60    match parser_result {
     61        Ok(mut parsed) => {
     62            *parser_error = match parsed.warnings.len() {
     63                0 => ptr::null(),
     64                _ => Box::into_raw(Box::new(parsed.warnings.remove(0))),
     65            };
     66            *session = Rc::into_raw(Rc::new(parsed));
     67            NS_OK
     68        }
     69        Err(e) => {
     70            *session = ptr::null();
     71            error!("Error parsing SDP in rust: {}", e);
     72            *parser_error = Box::into_raw(Box::new(e));
     73            NS_ERROR_INVALID_ARG
     74        }
     75    }
     76 }
     77 
     78 #[no_mangle]
     79 pub unsafe extern "C" fn create_anonymized_sdp_clone(
     80    session: *const SdpSession,
     81 ) -> *const SdpSession {
     82    Rc::into_raw(Rc::new(
     83        (*session).masked_clone(&mut StatefulSdpAnonymizer::new()),
     84    ))
     85 }
     86 
     87 #[no_mangle]
     88 pub unsafe extern "C" fn create_sdp_clone(session: *const SdpSession) -> *const SdpSession {
     89    Rc::into_raw(Rc::new((*session).clone()))
     90 }
     91 
     92 #[no_mangle]
     93 pub unsafe extern "C" fn sdp_free_session(sdp_ptr: *mut SdpSession) {
     94    let sdp = Rc::from_raw(sdp_ptr);
     95    drop(sdp);
     96 }
     97 
     98 #[no_mangle]
     99 pub unsafe extern "C" fn sdp_new_reference(session: *mut SdpSession) -> *const SdpSession {
    100    let original = Rc::from_raw(session);
    101    let ret = Rc::into_raw(Rc::clone(&original));
    102    std::mem::forget(original); // So the original reference doesn't get dropped
    103    ret
    104 }
    105 
    106 #[no_mangle]
    107 pub unsafe extern "C" fn sdp_get_error_line_num(parser_error: *mut SdpParserError) -> size_t {
    108    match *parser_error {
    109        SdpParserError::Line { line_number, .. }
    110        | SdpParserError::Unsupported { line_number, .. }
    111        | SdpParserError::Sequence { line_number, .. } => line_number,
    112    }
    113 }
    114 
    115 #[no_mangle]
    116 // Callee must check that a nullptr is not returned
    117 pub unsafe extern "C" fn sdp_get_error_message(parser_error: *mut SdpParserError) -> *mut c_char {
    118    let message = format!("{}", *parser_error);
    119    return match CString::new(message.as_str()) {
    120        Ok(c_char_ptr) => c_char_ptr.into_raw(),
    121        Err(_) => 0 as *mut c_char,
    122    };
    123 }
    124 
    125 #[no_mangle]
    126 pub unsafe extern "C" fn sdp_free_error_message(message: *mut c_char) {
    127    if message != 0 as *mut c_char {
    128        let _tmp = CString::from_raw(message);
    129    }
    130 }
    131 
    132 #[no_mangle]
    133 pub unsafe extern "C" fn sdp_free_error(parser_error: *mut SdpParserError) {
    134    let e = Box::from_raw(parser_error);
    135    drop(e);
    136 }
    137 
    138 #[no_mangle]
    139 pub unsafe extern "C" fn get_version(session: *const SdpSession) -> u64 {
    140    (*session).get_version()
    141 }
    142 
    143 #[no_mangle]
    144 pub unsafe extern "C" fn sdp_get_origin(session: *const SdpSession) -> RustSdpOrigin {
    145    origin_view_helper((*session).get_origin())
    146 }
    147 
    148 #[no_mangle]
    149 pub unsafe extern "C" fn session_view(session: *const SdpSession) -> StringView {
    150    StringView::from((*session).get_session())
    151 }
    152 
    153 #[no_mangle]
    154 pub unsafe extern "C" fn sdp_session_has_connection(session: *const SdpSession) -> bool {
    155    (*session).connection.is_some()
    156 }
    157 
    158 #[no_mangle]
    159 pub unsafe extern "C" fn sdp_get_session_connection(
    160    session: *const SdpSession,
    161    connection: *mut RustSdpConnection,
    162 ) -> nsresult {
    163    match (*session).connection {
    164        Some(ref c) => {
    165            *connection = RustSdpConnection::from(c);
    166            NS_OK
    167        }
    168        None => NS_ERROR_INVALID_ARG,
    169    }
    170 }
    171 
    172 #[no_mangle]
    173 pub unsafe extern "C" fn sdp_add_media_section(
    174    session: *mut SdpSession,
    175    media_type: u32,
    176    direction: u32,
    177    port: u16,
    178    protocol: u32,
    179    addr_type: u32,
    180    address: StringView,
    181 ) -> nsresult {
    182    let addr_type = match RustAddressType::try_from(addr_type) {
    183        Ok(a) => a.into(),
    184        Err(e) => {
    185            return e;
    186        }
    187    };
    188    let address_string: String = match address.try_into() {
    189        Ok(x) => x,
    190        Err(boxed_error) => {
    191            error!("Error while parsing string, description: {}", boxed_error);
    192            return NS_ERROR_INVALID_ARG;
    193        }
    194    };
    195    let address = match ExplicitlyTypedAddress::try_from((addr_type, address_string.as_str())) {
    196        Ok(a) => a,
    197        Err(_) => {
    198            return NS_ERROR_INVALID_ARG;
    199        }
    200    };
    201 
    202    let media_type = match media_type {
    203        0 => SdpMediaValue::Audio,       // MediaType::kAudio
    204        1 => SdpMediaValue::Video,       // MediaType::kVideo
    205        3 => SdpMediaValue::Application, // MediaType::kApplication
    206        _ => {
    207            return NS_ERROR_INVALID_ARG;
    208        }
    209    };
    210    let protocol = match protocol {
    211        20 => SdpProtocolValue::RtpSavpf,        // Protocol::kRtpSavpf
    212        21 => SdpProtocolValue::UdpTlsRtpSavp,   // Protocol::kUdpTlsRtpSavp
    213        22 => SdpProtocolValue::TcpDtlsRtpSavp,  // Protocol::kTcpDtlsRtpSavp
    214        24 => SdpProtocolValue::UdpTlsRtpSavpf,  // Protocol::kUdpTlsRtpSavpf
    215        25 => SdpProtocolValue::TcpDtlsRtpSavpf, // Protocol::kTcpTlsRtpSavpf
    216        37 => SdpProtocolValue::DtlsSctp,        // Protocol::kDtlsSctp
    217        38 => SdpProtocolValue::UdpDtlsSctp,     // Protocol::kUdpDtlsSctp
    218        39 => SdpProtocolValue::TcpDtlsSctp,     // Protocol::kTcpDtlsSctp
    219        _ => {
    220            return NS_ERROR_INVALID_ARG;
    221        }
    222    };
    223    let direction = match direction {
    224        1 => SdpAttribute::Sendonly,
    225        2 => SdpAttribute::Recvonly,
    226        3 => SdpAttribute::Sendrecv,
    227        _ => {
    228            return NS_ERROR_INVALID_ARG;
    229        }
    230    };
    231 
    232    match (*session).add_media(media_type, direction, port as u32, protocol, address) {
    233        Ok(_) => NS_OK,
    234        Err(_) => NS_ERROR_INVALID_ARG,
    235    }
    236 }
    237 
    238 #[repr(C)]
    239 #[derive(Clone)]
    240 pub struct RustSdpTiming {
    241    pub start: u64,
    242    pub stop: u64,
    243 }
    244 
    245 impl<'a> From<&'a SdpTiming> for RustSdpTiming {
    246    fn from(timing: &SdpTiming) -> Self {
    247        RustSdpTiming {
    248            start: timing.start,
    249            stop: timing.stop,
    250        }
    251    }
    252 }
    253 
    254 #[no_mangle]
    255 pub unsafe extern "C" fn sdp_session_has_timing(session: *const SdpSession) -> bool {
    256    (*session).timing.is_some()
    257 }
    258 
    259 #[no_mangle]
    260 pub unsafe extern "C" fn sdp_session_timing(
    261    session: *const SdpSession,
    262    timing: *mut RustSdpTiming,
    263 ) -> nsresult {
    264    match (*session).timing {
    265        Some(ref t) => {
    266            *timing = RustSdpTiming::from(t);
    267            NS_OK
    268        }
    269        None => NS_ERROR_INVALID_ARG,
    270    }
    271 }
    272 
    273 #[no_mangle]
    274 pub unsafe extern "C" fn sdp_media_section_count(session: *const SdpSession) -> size_t {
    275    (*session).media.len()
    276 }
    277 
    278 #[no_mangle]
    279 pub unsafe extern "C" fn get_sdp_bandwidth(
    280    session: *const SdpSession,
    281    bandwidth_type: *const c_char,
    282 ) -> u32 {
    283    get_bandwidth(&(*session).bandwidth, bandwidth_type)
    284 }
    285 
    286 #[no_mangle]
    287 pub unsafe extern "C" fn sdp_get_session_bandwidth_vec(
    288    session: *const SdpSession,
    289 ) -> *const Vec<SdpBandwidth> {
    290    &(*session).bandwidth
    291 }
    292 
    293 #[no_mangle]
    294 pub unsafe extern "C" fn get_sdp_session_attributes(
    295    session: *const SdpSession,
    296 ) -> *const Vec<SdpAttribute> {
    297    &(*session).attribute
    298 }