toe_beans/v4/message/
socket.rs1use super::Deliverable;
2use crate::v4::Result;
3use inherface::get_interfaces;
4use log::{debug, info};
5use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4, ToSocketAddrs, UdpSocket};
6
7pub struct Socket {
12 socket: UdpSocket,
13 broadcast: Ipv4Addr,
14}
15
16impl Socket {
17 pub fn new(address: SocketAddrV4, interface: Option<&String>) -> Self {
22 let broadcast = if cfg!(feature = "integration") {
24 Ipv4Addr::LOCALHOST
25 } else {
26 Self::get_interface_broadcast(interface).unwrap_or(Ipv4Addr::BROADCAST)
27 };
28
29 let socket = UdpSocket::bind(address).expect("failed to bind to address");
30 info!("UDP socket bound on {}", address);
31
32 socket
37 .set_broadcast(true)
38 .expect("Failed to enable broadcasting");
39
40 Self { socket, broadcast }
41 }
42
43 fn get_interface_broadcast(maybe_interface_name: Option<&String>) -> Option<Ipv4Addr> {
44 let interface = maybe_interface_name?;
45 let interfaces = get_interfaces().ok()?;
46 let maybe_interface = interfaces.get(interface);
47 let maybe_addr = maybe_interface?
48 .v4_addr
49 .iter()
50 .find(|address| address.broadcast.is_some());
51
52 debug!(
53 "found ipv4 broadcast address ({:?}) in list of addresses for interface",
54 maybe_addr
55 );
56
57 maybe_addr?.broadcast
58 }
59
60 pub fn get_ip(&self) -> Ipv4Addr {
64 match self.socket.local_addr().unwrap().ip() {
65 std::net::IpAddr::V4(ip) => ip,
66 std::net::IpAddr::V6(_) => todo!("ipv6 is not supported yet"),
67 }
68 }
69
70 pub fn receive<M: Deliverable<Output = M>>(&self) -> Result<(M, SocketAddr)> {
72 let mut bytes = [0; 548];
74 let (_, src) = match self.socket.recv_from(&mut bytes) {
75 Ok(values) => values,
76 Err(_) => return Err("Failed to receive data"),
77 };
78
79 let decoded = match M::from_bytes(&bytes) {
80 Ok(message) => message,
81 Err(_) => return Err("Failed decoding message"),
82 };
83
84 debug!("Received dhcp message (from {}): {:?}", src, decoded);
85
86 Ok((decoded, src))
87 }
88
89 pub fn unicast<A: ToSocketAddrs, M: Deliverable>(&self, message: &M, address: A) -> Result<()> {
91 let encoded = match message.to_bytes() {
92 Ok(bytes) => bytes,
93 Err(_) => return Err("Failed encoding message"),
94 };
95
96 let address = address.to_socket_addrs().unwrap().next().unwrap();
97 debug!("Sending dhcp message (to {:?}): {:?}", address, message);
98
99 match self.socket.send_to(&encoded, address) {
100 Ok(_) => Ok(()),
101 Err(_) => Err("Failed to send data"),
102 }
103 }
104
105 pub fn broadcast<M: Deliverable>(&self, message: &M, port: u16) -> Result<()> {
107 self.unicast(message, SocketAddr::new(IpAddr::V4(self.broadcast), port))
108 }
109}