e2e-irc/src/main.rs

136 lines
4.6 KiB
Rust
Raw Normal View History

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<dyn std::error::Error>> {
let args = env::args();
let server = args.collect::<Vec<String>>()[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<String, bool> = 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::<Vec<char>>()
.chunks(50)
.map(|c| c.iter().collect::<String>())
.collect::<Vec<String>>()
{
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<String> = 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)?;
}
}
}