bRAC/src/rac.rs
2025-02-10 09:01:06 +03:00

90 lines
2.5 KiB
Rust

use std::{error::Error, io::{Read, Write}, net::TcpStream, sync::{Arc, RwLock}, thread, time::Duration};
use super::{ADVERTISEMENT, ADVERTISEMENT_ENABLED, term::print_console, UPDATE_TIME};
pub fn send_message(host: &str, message: &str) -> Result<(), Box<dyn Error>> {
let mut stream = TcpStream::connect(host)?;
stream.write_all(&[0x01])?;
let data = format!("\r\x07{}{}{}",
message,
if message.chars().count() < 39 {
" ".repeat(39-message.chars().count())
} else {
String::new()
},
if ADVERTISEMENT_ENABLED {ADVERTISEMENT} else {""}
);
stream.write_all(data.as_bytes())?;
Ok(())
}
fn skip_null(stream: &mut TcpStream) -> Result<Vec<u8>, Box<dyn Error>> {
loop {
let mut buf = vec![0; 1];
stream.read_exact(&mut buf)?;
if buf[0] != 0 {
break Ok(buf)
}
}
}
fn read_messages(host: &str) -> Result<String, Box<dyn Error>> {
let mut stream = TcpStream::connect(host)?;
stream.write_all(&[0x00])?;
let packet_size = {
let mut data = skip_null(&mut stream)?;
loop {
let mut buf = vec![0; 1];
stream.read_exact(&mut buf)?;
let ch = buf[0];
if ch == 0 {
break
}
data.push(ch);
}
String::from_utf8(data)?
.trim_matches(char::from(0))
.parse()?
};
stream.write_all(&[0x01])?;
let packet_data = {
let mut data = skip_null(&mut stream)?;
while data.len() < packet_size {
let mut buf = vec![0; packet_size - data.len()];
let read_bytes = stream.read(&mut buf)?;
buf.truncate(read_bytes);
data.append(&mut buf);
}
String::from_utf8_lossy(&data).to_string()
};
Ok(packet_data)
}
fn recv_loop(host: &str, cache: Arc<RwLock<String>>, input: Arc<RwLock<String>>) -> Result<(), Box<dyn Error>> {
while let Ok(data) = read_messages(host) {
if data == cache.read().unwrap().clone() {
continue
}
*cache.write().unwrap() = data;
print_console(&cache.read().unwrap(), &input.read().unwrap())?;
thread::sleep(Duration::from_millis(UPDATE_TIME));
}
Ok(())
}
pub fn run_recv_loop(host: String, messages: Arc<RwLock<String>>, input: Arc<RwLock<String>>) {
thread::spawn({
move || {
let _ = recv_loop(&host, messages, input);
println!("Connection closed");
}
});
}