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 let (tx, rx) = mpsc::channel();
44 self.chan_to_thread = Some(tx);
45
46 let mut stream = TcpStream::connect(self.bind_addr.clone())?;
48 let callsign = self.callsign.clone();
49
50 Ok(thread::spawn(move || {
51 stream.read(&mut [0; 24]).unwrap();
53 stream
54 .write(&format!("{}\r\n", callsign).as_bytes())
55 .unwrap();
56
57 let mut stream_buffer = BufReader::new(stream);
59 let mut next_line = String::new();
60 loop {
61 match rx.try_recv() {
63 Ok(_) | Err(TryRecvError::Disconnected) => {
64 break;
65 }
66 Err(TryRecvError::Empty) => {}
67 }
68
69 next_line.clear();
71 stream_buffer.read_line(&mut next_line).unwrap();
72
73 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}