|
extern crate base64; // 0.13.0 |
|
extern crate sha2; // 0.9.5 |
|
|
|
use sha2::{Sha256, Sha512, Digest}; |
|
|
|
macro_rules! bits { |
|
($orig16BitWord:expr, $from:literal, $to:literal) => {{ |
|
let mask = ((1 << ($to - $from + 1)) - 1) << $from; |
|
($orig16BitWord & mask) >> $from |
|
}}; |
|
} |
|
|
|
fn main() { |
|
let kVersion = Version::kV1; |
|
let kPcp = Pcp::kP2pCluster; |
|
let kEndPointID = "AB12"; |
|
let kServiceIDHashBytes = std::str::from_utf8(&[0x0a, 0x0b, 0x0c]); |
|
let kEndPointName1 = "RAWK + ROWL!"; |
|
let kEndPointName2 = "How much wood can a woodchuck chuck if a wood chuck would chuck wood?"; |
|
let kWebRtcState = WebRtcState::kConnectable; |
|
let kFastAdvertisementEndpointName = "Fast Advertise"; |
|
let kBluetoothMacAddress = "00:00:E6:88:64:13"; |
|
|
|
let endpoint_info = kEndPointName2.as_bytes(); |
|
|
|
|
|
dbg!(endpoint_info); |
|
|
|
// create a Sha256 object |
|
let mut hasher = Sha256::new(); |
|
hasher.update(b"sid"); |
|
let service_id_hash = &hasher.finalize()[..3]; |
|
|
|
println!("service_id_hash: {:?}", service_id_hash); |
|
|
|
bluetooth_name_decode("ITR1ZEE0s2QAAAAAAAAABG5hbWU"); |
|
} |
|
|
|
|
|
|
|
fn bluetooth_name_decode(name: &str) { |
|
let decoded = base64::decode(name).expect("Error decoding!"); |
|
println!("bytes: {:?}", &decoded); |
|
|
|
/* The first 1 byte is supposed to be the version and pcp. */ |
|
// The upper 3 bits are supposed to be the version. |
|
let version = bits!(decoded[0], 0, 4); |
|
// The lower 5 bits are supposed to be the Pcp. |
|
let pcp = bits!(decoded[0], 5, 8); |
|
|
|
println!("version: {:05b}", version); |
|
println!("pcp: {:05b}", pcp); |
|
|
|
// The next 4 bytes are supposed to be the endpoint_id. |
|
let endpoint_id = std::str::from_utf8(&decoded[1..=4]); |
|
|
|
// The next 3 bytes are supposed to be the service_id_hash. |
|
let service_id_hash = &decoded[5..=7]; |
|
|
|
// The next 1 byte is field containning WebRtc state. |
|
let web_rtc_state = decoded[8]; |
|
|
|
println!("endpoint_id: {:?}", endpoint_id); |
|
println!("service_id_hash: {:?}", service_id_hash); |
|
println!("web_rtc_state: {}", web_rtc_state); |
|
|
|
// Next 6 bytes are padding '0' |
|
println!("reserved_padding: {:x?}", &decoded[9..=14]); |
|
|
|
let expected_endpoint_info_length = decoded[15]; |
|
println!( |
|
"expected_endpoint_info_length: {}", |
|
expected_endpoint_info_length |
|
); |
|
|
|
let endpoint_info = &decoded[16..=16 + expected_endpoint_info_length as usize - 1]; |
|
println!("endpoint_info: {:?}", std::str::from_utf8(&endpoint_info)); |
|
} |
|
|
|
enum Version { |
|
kUndefined = 0, |
|
kV1 = 1, |
|
// Version is only allocated 3 bits in the BluetoothDeviceName, so this |
|
// can never go beyond V7. |
|
} |
|
|
|
enum Pcp { |
|
kUnknown = 0, |
|
kP2pStar = 1, |
|
kP2pCluster = 2, |
|
kP2pPointToPoint = 3, |
|
// PCP is only allocated 5 bits in our data interchange formats, so there can |
|
// never be more than 31 PCP values. |
|
} |
|
|
|
// Represents the WebRtc state that mediums are connectable or not. |
|
enum WebRtcState { |
|
kUndefined = 0, |
|
kConnectable = 1, |
|
kUnconnectable = 2, |
|
} |