rbroadlink/network/
util.rs1use std::{
4 net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket},
5 slice::ChunksExact,
6 time::Duration,
7};
8
9pub fn checksum(data: &[u8]) -> u16 {
14 let mut sum = 0xBEAFu32;
16 for &d in data {
17 sum += u32::from(d);
18 }
19
20 return sum as u16;
21}
22
23pub fn compute_generic_checksum(buf: &[u8]) -> u16 {
30 let mut state: u32 = 0xFFFF;
31
32 let mut chunks_iter: ChunksExact<u8> = buf.chunks_exact(2);
33 while let Some(chunk) = chunks_iter.next() {
34 state += u16::from_le_bytes([chunk[0], chunk[1]]) as u32;
35 }
36
37 if let Some(&b) = chunks_iter.remainder().get(0) {
38 state += u16::from_le_bytes([b, 0]) as u32;
39 }
40
41 state = (state >> 16) + (state & 0xffff);
42 state = !state & 0xffff;
43
44 state as u16
45}
46
47pub fn local_ip_or(ip: Option<Ipv4Addr>) -> Result<IpAddr, String> {
49 Ok(match ip {
50 Some(ip) => IpAddr::V4(ip),
51 None => get_if_addrs::get_if_addrs()
52 .map_err(|e| {
53 format!(
54 "Could not automatically determine machine IP address. {}",
55 e
56 )
57 })?
58 .iter()
59 .find(|x| x.ip().is_ipv4() && !x.ip().is_loopback())
60 .ok_or("Could not find a local IPv4 address!")?
61 .ip(),
62 })
63}
64
65fn send_and_receive_impl(
67 msg: &[u8],
68 addr: Ipv4Addr,
69 port: Option<u16>,
70) -> Result<UdpSocket, String> {
71 let unspecified_addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, port.unwrap_or(0)));
73 let destination_addr = SocketAddr::from((addr, 80));
74
75 let socket = UdpSocket::bind(unspecified_addr)
78 .map_err(|e| format!("Could not bind to any port. {}", e))?;
79 socket
80 .set_broadcast(true)
81 .map_err(|e| format!("Could not enable broadcast. {}", e))?;
82
83 socket
85 .set_read_timeout(Some(Duration::new(10, 0)))
86 .map_err(|e| format!("Could not set read timeout! {}", e))?;
87 socket
88 .send_to(&msg, destination_addr)
89 .map_err(|e| format!("Could not broadcast message! {}", e))?;
90
91 return Ok(socket);
92}
93
94pub fn send_and_receive_many<I, T>(
96 msg: &[u8],
97 addr: Ipv4Addr,
98 port: Option<u16>,
99 cb: T,
100) -> Result<Vec<I>, String>
101where
102 T: Fn(usize, &[u8], SocketAddr) -> Result<I, String>,
103{
104 let socket = send_and_receive_impl(msg, addr, port)
106 .map_err(|e| format!("Could not create socket for message sending! {}", e))?;
107
108 let mut results: Vec<I> = vec![];
110 let mut recv_buffer = [0u8; 8092];
111 while let Ok((bytes_received, addr)) = socket.recv_from(&mut recv_buffer) {
112 results.push(cb(bytes_received, &recv_buffer[0..bytes_received], addr)?);
113 }
114
115 return Ok(results);
116}
117
118pub fn send_and_receive_one<I, T>(
120 msg: &[u8],
121 addr: Ipv4Addr,
122 port: Option<u16>,
123 cb: T,
124) -> Result<I, String>
125where
126 T: Fn(usize, &[u8], SocketAddr) -> Result<I, String>,
127{
128 let socket = send_and_receive_impl(msg, addr, port)
130 .map_err(|e| format!("Could not create socket for message sending! {}", e))?;
131
132 let mut recv_buffer = [0u8; 8092];
134 if let Ok((bytes_received, addr)) = socket.recv_from(&mut recv_buffer) {
135 return Ok(cb(bytes_received, &recv_buffer[0..bytes_received], addr)?);
136 }
137
138 return Err("No response within timeout!".into());
139}
140
141pub fn reverse_mac(mac_flipped: [u8; 6]) -> [u8; 6] {
143 let mut mac = [0u8; 6];
145 for i in 0..6 {
146 mac[i] = mac_flipped[6 - i - 1];
147 }
148
149 return mac;
150}