136 lines
4.6 KiB
Rust
136 lines
4.6 KiB
Rust
|
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)?;
|
||
|
}
|
||
|
}
|
||
|
}
|