rbn_lib/
lib.rs

1pub mod packet;
2
3use failure::Error;
4use regex::Regex;
5use std::{
6    io::{BufRead, BufReader, Read, Write},
7    sync::{mpsc::TryRecvError, Arc},
8    thread::JoinHandle,
9};
10use std::{
11    net::TcpStream,
12    sync::mpsc::{self, Sender},
13    thread,
14};
15
16use crate::packet::RbnPacket;
17
18
19pub struct RbnClient {
20    bind_addr: String,
21    callsign: String,
22    chan_to_thread: Option<Sender<bool>>,
23}
24
25impl RbnClient {
26    pub fn new(bind_addr: String, callsign: String) -> Self {
27        Self {
28            bind_addr,
29            callsign,
30            chan_to_thread: None,
31        }
32    }
33
34    pub fn new_default_addr(callsign: String) -> Self {
35        RbnClient::new("telnet.reversebeacon.net:7000".to_string(), callsign)
36    }
37
38    pub fn start(
39        &mut self,
40        callback: Arc<dyn Fn(packet::RbnPacket) + Send + Sync>,
41    ) -> Result<JoinHandle<()>, Error> {
42        // Set up mpsc to allow control of the thread
43        let (tx, rx) = mpsc::channel();
44        self.chan_to_thread = Some(tx);
45
46        // Get the stream for moving
47        let mut stream = TcpStream::connect(self.bind_addr.clone())?;
48        let callsign = self.callsign.clone();
49
50        Ok(thread::spawn(move || {
51            // Handle login
52            stream.read(&mut [0; 24]).unwrap();
53            stream
54                .write(&format!("{}\r\n", callsign).as_bytes())
55                .unwrap();
56
57            // Handle data
58            let mut stream_buffer = BufReader::new(stream);
59            let mut next_line = String::new();
60            loop {
61                // Check if we need to stop running
62                match rx.try_recv() {
63                    Ok(_) | Err(TryRecvError::Disconnected) => {
64                        break;
65                    }
66                    Err(TryRecvError::Empty) => {}
67                }
68
69                // Consume data from RBN
70                next_line.clear();
71                stream_buffer.read_line(&mut next_line).unwrap();
72
73                // Handle packets
74                let packet = next_line.parse();
75                if packet.is_ok() {
76                    callback(packet.unwrap());
77                }
78            }
79        }))
80    }
81
82    pub fn stop(&mut self) -> Result<(), Error> {
83        if self.chan_to_thread.is_some() {
84            self.chan_to_thread.as_ref().unwrap().send(true)?;
85        }
86        Ok(())
87    }
88}