1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! A full implementation of the Ether Dream laser protocol.

#[macro_use]
extern crate bitflags;
extern crate byteorder;

pub mod dac;
pub mod protocol;

use protocol::{ReadBytes, SizeBytes};
use std::{io, net};

/// An iterator that listens and waits for broadcast messages from DACs on the network and yields
/// them as they are received on the inner UDP socket.
///
/// Yields an `io::Error` if:
///
/// - An error occurred when receiving on the inner UDP socket.
/// - A `DacBroadcast` could not be read from the received bytes.
pub struct RecvDacBroadcasts {
    udp_socket: net::UdpSocket,
    buffer: [u8; RecvDacBroadcasts::BUFFER_LEN],
}

impl RecvDacBroadcasts {
    /// The size of the inner buffer used to receive broadcast messages.
    pub const BUFFER_LEN: usize = protocol::DacBroadcast::SIZE_BYTES;
}

/// Produces an iterator that listens and waits for broadcast messages from DACs on the network and
/// yields them as they are received on the inner UDP socket.
///
/// This function returns an `io::Error` if it could not bind to the broadcast address
/// `255.255.255.255:<protocol::BROADCAST_PORT>`.
///
/// The produced iterator yields an `io::Error` if:
///
/// - An error occurred when receiving on the inner UDP socket.
/// - A `DacBroadcast` could not be read from the received bytes.
///
/// ## Example
///
/// ```no_run
/// extern crate ether_dream;
///
/// fn main() {
///     let dac_broadcasts = ether_dream::recv_dac_broadcasts().expect("failed to bind to UDP socket");
///     for dac_broadcast in dac_broadcasts {
///         println!("{:#?}", dac_broadcast);
///     }
/// }
/// ```
pub fn recv_dac_broadcasts() -> io::Result<RecvDacBroadcasts> {
    let broadcast_port = protocol::BROADCAST_PORT;
    let broadcast_addr = net::SocketAddrV4::new([0, 0, 0, 0].into(), broadcast_port);
    let udp_socket = net::UdpSocket::bind(broadcast_addr)?;
    let buffer = [0; RecvDacBroadcasts::BUFFER_LEN];
    Ok(RecvDacBroadcasts { udp_socket, buffer })
}

impl Iterator for RecvDacBroadcasts {
    type Item = io::Result<(protocol::DacBroadcast, net::SocketAddr)>;
    fn next(&mut self) -> Option<Self::Item> {
        let RecvDacBroadcasts {
            ref mut buffer,
            ref mut udp_socket,
        } = *self;
        let (_len, src_addr) = match udp_socket.recv_from(buffer) {
            Ok(msg) => msg,
            Err(err) => return Some(Err(err)),
        };
        let mut bytes = &buffer[..];
        let dac_broadcast = match bytes.read_bytes::<protocol::DacBroadcast>() {
            Ok(dac_broadcast) => dac_broadcast,
            Err(err) => return Some(Err(err)),
        };
        Some(Ok((dac_broadcast, src_addr)))
    }
}