use crypto::RTCRandom;
use shared::error::{Error, Result};
use shared::util::generate_crypto_random_string;
#[cfg(test)]
mod rand_test;
const RUNES_ALPHA: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const RUNES_CANDIDATE_ID_FOUNDATION: &[u8] =
b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/+";
const LEN_UFRAG: usize = 16;
const LEN_PWD: usize = 32;
pub fn generate_cand_id() -> String {
format!(
"candidate:{}",
generate_crypto_random_string(32, RUNES_CANDIDATE_ID_FOUNDATION)
)
}
fn generate_string_with_random(
length: usize,
alphabet: &[u8],
random: &dyn RTCRandom,
) -> Result<String> {
debug_assert!(!alphabet.is_empty() && alphabet.len() <= u8::MAX as usize + 1);
let acceptance_limit = 256 - (256 % alphabet.len());
let mut output = String::with_capacity(length);
let mut random_bytes = [0_u8; 64];
while output.len() < length {
random
.fill(&mut random_bytes)
.map_err(|error| Error::Crypto(error.to_string()))?;
for byte in random_bytes {
if byte as usize >= acceptance_limit {
continue;
}
output.push(alphabet[byte as usize % alphabet.len()] as char);
if output.len() == length {
break;
}
}
}
Ok(output)
}
pub fn generate_pwd() -> String {
generate_crypto_random_string(LEN_PWD, RUNES_ALPHA)
}
pub(crate) fn generate_pwd_with_random(random: &dyn RTCRandom) -> Result<String> {
generate_string_with_random(LEN_PWD, RUNES_ALPHA, random)
}
pub(crate) fn generate_tie_breaker(random: &dyn RTCRandom) -> Result<u64> {
let mut bytes = [0_u8; std::mem::size_of::<u64>()];
random
.fill(&mut bytes)
.map_err(|error| Error::Crypto(error.to_string()))?;
Ok(u64::from_be_bytes(bytes))
}
pub fn generate_ufrag() -> String {
generate_crypto_random_string(LEN_UFRAG, RUNES_ALPHA)
}
pub(crate) fn generate_ufrag_with_random(random: &dyn RTCRandom) -> Result<String> {
generate_string_with_random(LEN_UFRAG, RUNES_ALPHA, random)
}