candid_server 0.3.1

A server for reading and relaying messages on a CAN bus
Documentation
use std::sync::{mpsc, Arc, Mutex};
use std::thread;

use socketcan::{CanFrame, CanSocket, Socket};

/// Reads from the opened CAN socket and relays each frame to each stored client
pub struct CANReader {
    can_socket: Arc<Mutex<CanSocket>>,
    clients: Arc<Mutex<Vec<mpsc::Sender<CanFrame>>>>,
}

impl CANReader {
    /// Creates a new `CANReader` from the given socket. Spawns one thread for reading frames
    pub fn new(socket: CanSocket) -> (CANReader, thread::JoinHandle<()>) {
        let reader = CANReader {
            can_socket: Arc::new(Mutex::new(socket)),
            clients: Arc::new(Mutex::new(Vec::new())),
        };

        // Spawn thread for reader runtime
        let can_socket = Arc::clone(&reader.can_socket); // Thread takes ownership of these
        let clients = Arc::clone(&reader.clients);
        let handle = thread::spawn(move || {
            loop {
                // Read a frame from the socket.
                let frame = can_socket.lock().unwrap().read_frame().unwrap();

                // Write it to each client
                let mut dropped_clients = Vec::new();
                for (i, client) in clients.lock().unwrap().iter().enumerate() {
                    client.send(frame).unwrap_or_else(|_| {
                        // Indicate that this client's connection has been dropped
                        dropped_clients.push(i);
                    });
                }

                // Clean up dropped clients
                for i in dropped_clients {
                    clients.lock().unwrap().remove(i);
                }
            }
        });

        (reader, handle)
    }

    /// Registers a client with this `CANReader`
    pub fn add_client(&self, channel: mpsc::Sender<CanFrame>) {
        self.clients.lock().unwrap().push(channel);
    }

    /// Returns a copy of the underlying `CANsocket`
    pub fn get_socket(&self) -> Arc<Mutex<CanSocket>> {
        Arc::clone(&self.can_socket)
    }
}