Skip to content

Commit

Permalink
rtc-ice add back candidates
Browse files Browse the repository at this point in the history
  • Loading branch information
yngrtc committed Mar 9, 2024
1 parent 5a29845 commit 0732397
Show file tree
Hide file tree
Showing 14 changed files with 1,022 additions and 33 deletions.
183 changes: 167 additions & 16 deletions rtc-ice/src/candidate/candidate_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use std::time::{Duration, Instant};

use super::*;
use crate::candidate::candidate_host::CandidateHostConfig;
use crate::candidate::candidate_peer_reflexive::CandidatePeerReflexiveConfig;
use crate::candidate::candidate_relay::CandidateRelayConfig;
use crate::candidate::candidate_server_reflexive::CandidateServerReflexiveConfig;
use crate::network_type::determine_network_type;
use shared::error::*;

#[derive(Default)]
Expand All @@ -21,13 +25,14 @@ pub struct CandidateBaseConfig {

pub struct CandidateBase {
pub(crate) id: String,
pub(crate) network_type: u8,
pub(crate) network_type: NetworkType,
pub(crate) candidate_type: CandidateType,

pub(crate) component: u16,
pub(crate) address: String,
pub(crate) port: u16,
pub(crate) related_address: Option<CandidateRelatedAddress>,
pub(crate) tcp_type: TcpType,

pub(crate) resolved_addr: SocketAddr,

Expand All @@ -41,19 +46,22 @@ pub struct CandidateBase {

//CandidateHost
pub(crate) network: String,
//CandidateRelay
//TODO: pub(crate) relay_client: Option<Arc<turn::client::Client>>,
}

impl Default for CandidateBase {
fn default() -> Self {
Self {
id: String::new(),
network_type: 0,
network_type: NetworkType::Unspecified,
candidate_type: CandidateType::default(),

component: 0,
address: String::new(),
port: 0,
related_address: None,
tcp_type: TcpType::default(),

resolved_addr: SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 0),

Expand All @@ -65,6 +73,7 @@ impl Default for CandidateBase {
foundation_override: String::new(),
priority_override: 0,
network: String::new(),
//TODO: relay_client: None,
}
}
}
Expand All @@ -75,7 +84,8 @@ impl fmt::Display for CandidateBase {
if let Some(related_address) = self.related_address() {
write!(
f,
"{} {}:{}{}",
"{} {} {}:{}{}",
self.network_type(),
self.candidate_type(),
self.address(),
self.port(),
Expand All @@ -84,7 +94,8 @@ impl fmt::Display for CandidateBase {
} else {
write!(
f,
"{} {}:{}",
"{} {} {}:{}",
self.network_type(),
self.candidate_type(),
self.address(),
self.port(),
Expand All @@ -102,6 +113,7 @@ impl Candidate for CandidateBase {
let mut buf = vec![];
buf.extend_from_slice(self.candidate_type().to_string().as_bytes());
buf.extend_from_slice(self.address.as_bytes());
buf.extend_from_slice(self.network_type().to_string().as_bytes());

let checksum = Crc::<u32>::new(&CRC_32_ISCSI).checksum(&buf);

Expand Down Expand Up @@ -132,6 +144,11 @@ impl Candidate for CandidateBase {
self.baseline_time + Duration::from_nanos(self.last_sent.load(Ordering::SeqCst))
}

/// Returns candidate NetworkType.
fn network_type(&self) -> NetworkType {
self.network_type
}

/// Returns Candidate Address.
fn address(&self) -> String {
self.address.clone()
Expand Down Expand Up @@ -169,18 +186,27 @@ impl Candidate for CandidateBase {
self.candidate_type
}

fn tcp_type(&self) -> TcpType {
self.tcp_type
}

/// Returns the string representation of the ICECandidate.
fn marshal(&self) -> String {
let mut val = format!(
"{} {} {} {} {} typ {}",
"{} {} {} {} {} {} typ {}",
self.foundation(),
self.component(),
self.network_type().network_short(),
self.priority(),
self.address(),
self.port(),
self.candidate_type()
);

if self.tcp_type != TcpType::Unspecified {
val += format!(" tcptype {}", self.tcp_type()).as_str();
}

if let Some(related_address) = self.related_address() {
val += format!(
" raddr {} rport {}",
Expand Down Expand Up @@ -232,13 +258,17 @@ impl Candidate for CandidateBase {

/// Used to compare two candidateBases.
fn equal(&self, other: &dyn Candidate) -> bool {
self.candidate_type() == other.candidate_type()
self.network_type() == other.network_type()
&& self.candidate_type() == other.candidate_type()
&& self.address() == other.address()
&& self.port() == other.port()
&& self.tcp_type() == other.tcp_type()
&& self.related_address() == other.related_address()
}

fn set_ip(&mut self, ip: &IpAddr) -> Result<()> {
let network_type = determine_network_type(&self.network, ip)?;
self.network_type = network_type;
self.resolved_addr = SocketAddr::new(*ip, self.port);

Ok(())
Expand All @@ -261,7 +291,66 @@ impl CandidateBase {

/// Returns the local preference for this candidate.
pub fn local_preference(&self) -> u16 {
DEFAULT_LOCAL_PREFERENCE
if self.network_type().is_tcp() {
// RFC 6544, section 4.2
//
// In Section 4.1.2.1 of [RFC5245], a recommended formula for UDP ICE
// candidate prioritization is defined. For TCP candidates, the same
// formula and candidate type preferences SHOULD be used, and the
// RECOMMENDED type preferences for the new candidate types defined in
// this document (see Section 5) are 105 for NAT-assisted candidates and
// 75 for UDP-tunneled candidates.
//
// (...)
//
// With TCP candidates, the local preference part of the recommended
// priority formula is updated to also include the directionality
// (active, passive, or simultaneous-open) of the TCP connection. The
// RECOMMENDED local preference is then defined as:
//
// local preference = (2^13) * direction-pref + other-pref
//
// The direction-pref MUST be between 0 and 7 (both inclusive), with 7
// being the most preferred. The other-pref MUST be between 0 and 8191
// (both inclusive), with 8191 being the most preferred. It is
// RECOMMENDED that the host, UDP-tunneled, and relayed TCP candidates
// have the direction-pref assigned as follows: 6 for active, 4 for
// passive, and 2 for S-O. For the NAT-assisted and server reflexive
// candidates, the RECOMMENDED values are: 6 for S-O, 4 for active, and
// 2 for passive.
//
// (...)
//
// If any two candidates have the same type-preference and direction-
// pref, they MUST have a unique other-pref. With this specification,
// this usually only happens with multi-homed hosts, in which case
// other-pref is the preference for the particular IP address from which
// the candidate was obtained. When there is only a single IP address,
// this value SHOULD be set to the maximum allowed value (8191).
let other_pref: u16 = 8191;

let direction_pref: u16 = match self.candidate_type() {
CandidateType::Host | CandidateType::Relay => match self.tcp_type() {
TcpType::Active => 6,
TcpType::Passive => 4,
TcpType::SimultaneousOpen => 2,
TcpType::Unspecified => 0,
},
CandidateType::PeerReflexive | CandidateType::ServerReflexive => {
match self.tcp_type() {
TcpType::SimultaneousOpen => 6,
TcpType::Active => 4,
TcpType::Passive => 2,
TcpType::Unspecified => 0,
}
}
CandidateType::Unspecified => 0,
};

(1 << 13) * direction_pref + other_pref
} else {
DEFAULT_LOCAL_PREFERENCE
}
}
}

Expand Down Expand Up @@ -296,23 +385,35 @@ pub fn unmarshal_candidate(raw: &str) -> Result<impl Candidate> {

let typ = split[7];

//let mut rel_addr = String::new();
//let mut rel_port = 0;
let mut rel_addr = String::new();
let mut rel_port = 0;
let mut tcp_type = TcpType::Unspecified;

if split.len() > 8 {
let split2 = &split[8..];

if split2[0] == "raddr" && split2.len() < 4 {
return Err(Error::Other(format!(
"{:?}: incorrect length",
Error::ErrParseRelatedAddr
)));
if split2[0] == "raddr" {
if split2.len() < 4 {
return Err(Error::Other(format!(
"{:?}: incorrect length",
Error::ErrParseRelatedAddr
)));
}

// RelatedAddress
//rel_addr = split2[1].to_owned();
rel_addr = split2[1].to_owned();

// RelatedPort
//rel_port = split2[3].parse()?;
rel_port = split2[3].parse()?;
} else if split2[0] == "tcptype" {
if split2.len() < 2 {
return Err(Error::Other(format!(
"{:?}: incorrect length",
Error::ErrParseType
)));
}

tcp_type = TcpType::from(split2[1]);
}
}

Expand All @@ -328,9 +429,59 @@ pub fn unmarshal_candidate(raw: &str) -> Result<impl Candidate> {
foundation,
..CandidateBaseConfig::default()
},
tcp_type,
};
config.new_candidate_host()
}
"srflx" => {
let config = CandidateServerReflexiveConfig {
base_config: CandidateBaseConfig {
network,
address,
port,
component,
priority,
foundation,
..CandidateBaseConfig::default()
},
rel_addr,
rel_port,
};
config.new_candidate_server_reflexive()
}
"prflx" => {
let config = CandidatePeerReflexiveConfig {
base_config: CandidateBaseConfig {
network,
address,
port,
component,
priority,
foundation,
..CandidateBaseConfig::default()
},
rel_addr,
rel_port,
};

config.new_candidate_peer_reflexive()
}
"relay" => {
let config = CandidateRelayConfig {
base_config: CandidateBaseConfig {
network,
address,
port,
component,
priority,
foundation,
..CandidateBaseConfig::default()
},
rel_addr,
rel_port,
};
config.new_candidate_relay()
}
_ => Err(Error::Other(format!(
"{:?} ({})",
Error::ErrUnknownCandidateType,
Expand Down
10 changes: 7 additions & 3 deletions rtc-ice/src/candidate/candidate_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use crate::rand::generate_cand_id;
#[derive(Default)]
pub struct CandidateHostConfig {
pub base_config: CandidateBaseConfig,

pub tcp_type: TcpType,
}

impl CandidateHostConfig {
Expand All @@ -16,22 +18,24 @@ impl CandidateHostConfig {
candidate_id = generate_cand_id();
}

let c = CandidateBase {
let mut c = CandidateBase {
id: candidate_id,
address: self.base_config.address.clone(),
candidate_type: CandidateType::Host,
component: self.base_config.component,
port: self.base_config.port,
tcp_type: self.tcp_type,
foundation_override: self.base_config.foundation,
priority_override: self.base_config.priority,
network: self.base_config.network,
network_type: NetworkType::Udp4,
//conn: self.base_config.conn,
..CandidateBase::default()
};

if !self.base_config.address.ends_with(".local") {
//TODO: let ip = self.base_config.address.parse()?;
//TODO: c.set_ip(&ip)?;
let ip = self.base_config.address.parse()?;
c.set_ip(&ip)?;
};

Ok(c)
Expand Down
Loading

0 comments on commit 0732397

Please sign in to comment.