network.rs (7635B)
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 nserror; 6 7 use std::ffi::{CStr, CString}; 8 use std::net::IpAddr; 9 use std::os::raw::c_char; 10 11 use rsdparsa::address::{Address, AddressType, AddressTyped, ExplicitlyTypedAddress}; 12 use rsdparsa::{SdpBandwidth, SdpConnection, SdpOrigin}; 13 use std::convert::TryFrom; 14 use types::{StringView, NULL_STRING}; 15 16 #[repr(C)] 17 #[derive(Clone, Copy, PartialEq)] 18 pub enum RustAddressType { 19 IP4, 20 IP6, 21 } 22 23 impl TryFrom<u32> for RustAddressType { 24 type Error = nserror::nsresult; 25 fn try_from(address_type: u32) -> Result<Self, Self::Error> { 26 match address_type { 27 1 => Ok(RustAddressType::IP4), 28 2 => Ok(RustAddressType::IP6), 29 _ => Err(nserror::NS_ERROR_INVALID_ARG), 30 } 31 } 32 } 33 34 impl From<AddressType> for RustAddressType { 35 fn from(address_type: AddressType) -> Self { 36 match address_type { 37 AddressType::IpV4 => RustAddressType::IP4, 38 AddressType::IpV6 => RustAddressType::IP6, 39 } 40 } 41 } 42 43 impl Into<AddressType> for RustAddressType { 44 fn into(self) -> AddressType { 45 match self { 46 RustAddressType::IP4 => AddressType::IpV4, 47 RustAddressType::IP6 => AddressType::IpV6, 48 } 49 } 50 } 51 52 impl<'a> From<&'a IpAddr> for RustAddressType { 53 fn from(addr: &IpAddr) -> RustAddressType { 54 addr.address_type().into() 55 } 56 } 57 58 pub fn get_octets(addr: &IpAddr) -> [u8; 16] { 59 let mut octets = [0; 16]; 60 match *addr { 61 IpAddr::V4(v4_addr) => { 62 let v4_octets = v4_addr.octets(); 63 (&mut octets[0..4]).copy_from_slice(&v4_octets); 64 } 65 IpAddr::V6(v6_addr) => { 66 let v6_octets = v6_addr.octets(); 67 octets.copy_from_slice(&v6_octets); 68 } 69 } 70 octets 71 } 72 73 #[repr(C)] 74 pub struct RustAddress { 75 ip_address: [u8; 50], 76 fqdn: StringView, 77 is_fqdn: bool, 78 } 79 80 impl<'a> From<&'a Address> for RustAddress { 81 fn from(address: &Address) -> Self { 82 match address { 83 Address::Ip(ip) => Self::from(ip), 84 Address::Fqdn(fqdn) => Self { 85 ip_address: [0; 50], 86 fqdn: fqdn.as_str().into(), 87 is_fqdn: true, 88 }, 89 } 90 } 91 } 92 93 impl<'a> From<&'a IpAddr> for RustAddress { 94 fn from(addr: &IpAddr) -> Self { 95 let mut c_addr = [0; 50]; 96 let str_addr = format!("{}", addr); 97 let str_bytes = str_addr.as_bytes(); 98 if str_bytes.len() < 50 { 99 c_addr[..str_bytes.len()].copy_from_slice(&str_bytes); 100 } 101 Self { 102 ip_address: c_addr, 103 fqdn: NULL_STRING, 104 is_fqdn: false, 105 } 106 } 107 } 108 109 #[repr(C)] 110 pub struct RustExplicitlyTypedAddress { 111 address_type: RustAddressType, 112 address: RustAddress, 113 } 114 115 impl Default for RustExplicitlyTypedAddress { 116 fn default() -> Self { 117 Self { 118 address_type: RustAddressType::IP4, 119 address: RustAddress { 120 ip_address: [0; 50], 121 fqdn: NULL_STRING, 122 is_fqdn: false, 123 }, 124 } 125 } 126 } 127 128 impl<'a> From<&'a ExplicitlyTypedAddress> for RustExplicitlyTypedAddress { 129 fn from(address: &ExplicitlyTypedAddress) -> Self { 130 match address { 131 ExplicitlyTypedAddress::Fqdn { domain, .. } => Self { 132 address_type: address.address_type().into(), 133 address: RustAddress { 134 ip_address: [0; 50], 135 fqdn: StringView::from(domain.as_str()), 136 is_fqdn: true, 137 }, 138 }, 139 ExplicitlyTypedAddress::Ip(ip_address) => Self { 140 address_type: ip_address.address_type().into(), 141 address: ip_address.into(), 142 }, 143 } 144 } 145 } 146 147 // TODO @@NG remove 148 impl<'a> From<&'a Option<IpAddr>> for RustExplicitlyTypedAddress { 149 fn from(addr: &Option<IpAddr>) -> Self { 150 match *addr { 151 Some(ref x) => Self { 152 address_type: RustAddressType::from(x.address_type()), 153 address: RustAddress::from(x), 154 }, 155 None => Self::default(), 156 } 157 } 158 } 159 160 #[repr(C)] 161 pub struct RustSdpConnection { 162 pub addr: RustExplicitlyTypedAddress, 163 pub ttl: u8, 164 pub amount: u64, 165 } 166 167 impl<'a> From<&'a SdpConnection> for RustSdpConnection { 168 fn from(sdp_connection: &SdpConnection) -> Self { 169 let ttl = match sdp_connection.ttl { 170 Some(x) => x as u8, 171 None => 0, 172 }; 173 let amount = match sdp_connection.amount { 174 Some(x) => x as u64, 175 None => 0, 176 }; 177 RustSdpConnection { 178 addr: RustExplicitlyTypedAddress::from(&sdp_connection.address), 179 ttl: ttl, 180 amount: amount, 181 } 182 } 183 } 184 185 #[repr(C)] 186 pub struct RustSdpOrigin { 187 username: StringView, 188 session_id: u64, 189 session_version: u64, 190 addr: RustExplicitlyTypedAddress, 191 } 192 193 fn bandwidth_match(str_bw: &str, enum_bw: &SdpBandwidth) -> bool { 194 match *enum_bw { 195 SdpBandwidth::As(_) => str_bw == "AS", 196 SdpBandwidth::Ct(_) => str_bw == "CT", 197 SdpBandwidth::Tias(_) => str_bw == "TIAS", 198 SdpBandwidth::Unknown(ref type_name, _) => str_bw == type_name, 199 } 200 } 201 202 fn bandwidth_value(bandwidth: &SdpBandwidth) -> u32 { 203 match *bandwidth { 204 SdpBandwidth::As(x) | SdpBandwidth::Ct(x) | SdpBandwidth::Tias(x) => x, 205 SdpBandwidth::Unknown(_, _) => 0, 206 } 207 } 208 209 pub unsafe fn get_bandwidth(bandwidths: &Vec<SdpBandwidth>, bandwidth_type: *const c_char) -> u32 { 210 let bw_type = match CStr::from_ptr(bandwidth_type).to_str() { 211 Ok(string) => string, 212 Err(_) => return 0, 213 }; 214 for bandwidth in bandwidths.iter() { 215 if bandwidth_match(bw_type, bandwidth) { 216 return bandwidth_value(bandwidth); 217 } 218 } 219 0 220 } 221 222 #[no_mangle] 223 pub unsafe extern "C" fn sdp_serialize_bandwidth(bw: *const Vec<SdpBandwidth>) -> *mut c_char { 224 let mut builder = String::new(); 225 for bandwidth in (*bw).iter() { 226 match *bandwidth { 227 SdpBandwidth::As(val) => { 228 builder.push_str("b=AS:"); 229 builder.push_str(&val.to_string()); 230 builder.push_str("\r\n"); 231 } 232 SdpBandwidth::Ct(val) => { 233 builder.push_str("b=CT:"); 234 builder.push_str(&val.to_string()); 235 builder.push_str("\r\n"); 236 } 237 SdpBandwidth::Tias(val) => { 238 builder.push_str("b=TIAS:"); 239 builder.push_str(&val.to_string()); 240 builder.push_str("\r\n"); 241 } 242 SdpBandwidth::Unknown(ref name, val) => { 243 builder.push_str("b="); 244 builder.push_str(name.as_str()); 245 builder.push(':'); 246 builder.push_str(&val.to_string()); 247 builder.push_str("\r\n"); 248 } 249 } 250 } 251 CString::from_vec_unchecked(builder.into_bytes()).into_raw() 252 } 253 254 #[no_mangle] 255 pub unsafe extern "C" fn sdp_free_string(s: *mut c_char) { 256 drop(CString::from_raw(s)); 257 } 258 259 pub unsafe fn origin_view_helper(origin: &SdpOrigin) -> RustSdpOrigin { 260 RustSdpOrigin { 261 username: StringView::from(origin.username.as_str()), 262 session_id: origin.session_id, 263 session_version: origin.session_version, 264 addr: RustExplicitlyTypedAddress::from(&origin.unicast_addr), 265 } 266 }