use base64::{engine::general_purpose, Engine as _}; use ircparser; use std::collections::HashMap; use std::net::{Shutdown, TcpStream}; use std::sync::mpsc; use std::thread; use std::{env, fs}; mod encryption; mod listener_server; mod message_stream; mod writer_client; macro_rules! try_recv { ($rx:ident) => { match $rx.try_recv() { Ok(recieved) => recieved, Err(_e) => match _e { mpsc::TryRecvError::Empty => String::new(), mpsc::TryRecvError::Disconnected => { panic!("Error!") } }, } }; } fn main() -> Result<(), Box> { let args = env::args(); let server = args.collect::>()[1].clone(); let stream = TcpStream::connect(format!("{server}:6697"))?; let public_key = general_purpose::STANDARD.encode(fs::read("public.asc")?); let secret_key = general_purpose::STANDARD.encode(fs::read("secret.asc")?); let reader_stream = match stream.try_clone() { Ok(stream) => stream, Err(_error) => { let _ = stream.shutdown(Shutdown::Both); panic!("Failed to create the reader stream") } }; let writer_stream = match stream.try_clone() { Ok(stream) => stream, Err(_error) => { let _ = stream.shutdown(Shutdown::Both); let _ = reader_stream.shutdown(Shutdown::Both); panic!("Failed to create the writer stream") } }; let (listener_channel_send_tx, listener_channel_rx) = mpsc::channel(); let (listener_channel_tx, listener_channel_recv_rx) = mpsc::channel(); let (writer_channel_tx, writer_channel_send_rx) = mpsc::channel(); let (writer_channel_recv_tx, writer_channel_rx) = mpsc::channel(); thread::spawn(|| { listener_server::listen_to_client(listener_channel_send_tx, listener_channel_recv_rx) }); thread::spawn(|| { writer_client::write_to_server( writer_stream, server, writer_channel_send_rx, writer_channel_recv_tx, ) }); let mut negotiated_users: HashMap = HashMap::new(); loop { let recieved = try_recv!(listener_channel_rx); if recieved != "" { let command = &ircparser::parse(&recieved).expect("Got an invalid IRC instruction")[0]; if command.command == "PRIVMSG" && !command.params[0].starts_with("#") { if !negotiated_users.get(&command.params[0]).is_none() { dbg!(recieved); let reciever = &command.params[0]; writer_channel_tx.send(format!("PRIVMSG {reciever} START_KEY\n"))?; for line in public_key .chars() .collect::>() .chunks(50) .map(|c| c.iter().collect::()) .collect::>() { dbg!(&line); writer_channel_tx .send(format!("PRIVMSG {reciever} {}", line.clone() + "\n"))?; } writer_channel_tx.send(format!("PRIVMSG {reciever} END_KEY\n"))?; let mut foreign_key: Vec = Vec::new(); while !foreign_key.contains(&"END_KEY".to_string()) { dbg!("Trying to recv"); let recieved_raw = writer_channel_rx.recv()?; dbg!(&recieved_raw); let recieved = &ircparser::parse(&recieved_raw).unwrap()[0]; let begin_source_reciever = format!(":{reciever}!"); if recieved.command != "PRIVMSG" || !recieved .source .clone() .unwrap_or("".to_string()) .starts_with(&begin_source_reciever) { writer_channel_tx.send(recieved_raw)?; continue; } foreign_key.push(recieved.params[1].clone()); } foreign_key.pop(); } } else { dbg!(&recieved); writer_channel_tx.send(recieved)?; } } let recieved = try_recv!(writer_channel_rx); if recieved != "" { dbg!(&recieved); listener_channel_tx.send(recieved)?; } } }