use argparse::{ArgumentParser, Store}; use dirs::config_local_dir; use eyre::Result; use helpers::State; use pgp::{Deserializable, SignedPublicKey, SignedSecretKey}; use std::collections::HashMap; use std::fs; use std::sync::mpsc; use std::thread; use std::time::Duration; use toml::Table; mod client_handler; mod encryption; mod helpers; mod listener_server; mod server_handler; mod writer_client; fn main() -> Result<()> { let config_file = config_local_dir() .expect("Couldn't get config directory") .join("e2e-irc/config.toml"); if !config_file.exists() { panic!("Create a config file at {}", config_file.display()); } let parsed_config = String::from_utf8_lossy(&fs::read(config_file)?).parse::()?; let public_key_location = parsed_config .get("public_key") .expect("Coudln't get public_key. Try creating it in the config") .as_str() .expect("Couldn't convert public_key to str"); let secret_key_location = parsed_config .get("secret_key") .expect("Coudln't get secret_key. Try creating it in the config") .as_str() .expect("Couldn't convert secret_key to str"); let default_password = toml::Value::String(String::new()); let passwd = parsed_config .get("passwd") .unwrap_or(&default_password) .as_str() .expect("Coudln't convert passwd to str"); let mut server = "irc.vanten-s.com".to_string(); let mut port = "6666".to_string(); let mut server_port = "6697".to_string(); { let mut ap = ArgumentParser::new(); ap.set_description("Encrypted IRC Bouncer"); ap.refer(&mut server) .add_argument( "server", Store, "The Address Of The Server The Bouncer Connects To", ) .required(); ap.refer(&mut port) .add_option(&["-p", "--port"], Store, "The Port The Bouncer Binds To"); ap.refer(&mut server_port).add_option( &["--sp", "--server-port"], Store, "The TLS Enabled Port Of The Server", ); ap.parse_args_or_exit(); } let public_key = fs::read(public_key_location)?; let secret_key = SignedSecretKey::from_bytes(fs::read(secret_key_location)?.as_slice())?; 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(); let tmp_port = port.clone(); thread::spawn(move || { listener_server::listen_to_client( listener_channel_send_tx, listener_channel_recv_rx, tmp_port, ) }); let tmp_port = server_port.clone(); let tmp_server = server.clone(); thread::spawn(move || { writer_client::write_to_server( &tmp_server, &tmp_port, writer_channel_send_rx, writer_channel_recv_tx, ) }); let mut keys: HashMap = HashMap::new(); let mut state = State::new(); loop { match listener_channel_rx.try_recv() { Ok(message) => { let _ = client_handler::handle_message_from_client( &message, &public_key, &server, &mut keys, &writer_channel_tx, &writer_channel_rx, &listener_channel_tx, &listener_channel_rx, &mut state, ); } Err(error) => match error { mpsc::TryRecvError::Empty => {} mpsc::TryRecvError::Disconnected => panic!("listener_channel_rx disconnected"), }, }; match writer_channel_rx.try_recv() { Ok(message) => { let _ = server_handler::handle_message_from_server( &message, &public_key, &secret_key, &server, passwd, &mut keys, &writer_channel_tx, &writer_channel_rx, &listener_channel_tx, &listener_channel_rx, &state, ); } Err(error) => match error { mpsc::TryRecvError::Empty => {} mpsc::TryRecvError::Disconnected => panic!("writer_channel_rx disconnected"), }, }; thread::sleep(Duration::from_millis(1)); } }