ping no worky

This commit is contained in:
2025-03-06 14:24:01 +01:00
parent e8630c2e5b
commit 1d69387dc8

View File

@@ -1,4 +1,4 @@
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use std::{io::Cursor, net::SocketAddr, str::FromStr, sync::Arc, time::Duration}; use std::{io::Cursor, net::SocketAddr, str::FromStr, sync::Arc, time::Duration};
use irc_rust::Message; use irc_rust::Message;
@@ -12,29 +12,37 @@ use tokio::{
}; };
use tokio_rustls::{TlsAcceptor, server::TlsStream}; use tokio_rustls::{TlsAcceptor, server::TlsStream};
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
#[derive(Debug)] #[derive(Debug)]
struct Client { struct Client {
peer_addr: SocketAddr,
rx: Receiver<Message>, rx: Receiver<Message>,
tx: Sender<Message>, tx: Sender<Message>,
nick: Option<String>, nick: Option<String>,
username: Option<String>,
realname: Option<String>,
modes: HashSet<u8>, // [byte per mode](https://www.unrealircd.org/docs/User_modes)
c2s_tx: Option<Sender<Message>>, c2s_tx: Option<Sender<Message>>,
s2c_rx: Option<Receiver<Message>>, s2c_rx: Option<Receiver<Message>>,
} }
impl Client { impl Client {
pub fn new(peer_addr: SocketAddr) -> Self { pub fn new() -> Self {
let (c2s_tx, c2s_rx) = mpsc::channel(32); let (c2s_tx, c2s_rx) = mpsc::channel(32);
let (s2c_tx, s2c_rx) = mpsc::channel(32); let (s2c_tx, s2c_rx) = mpsc::channel(32);
Self { Self {
peer_addr,
tx: s2c_tx, tx: s2c_tx,
rx: c2s_rx, rx: c2s_rx,
nick: None, nick: None,
username: None,
realname: None,
modes: HashSet::new(),
c2s_tx: Some(c2s_tx), c2s_tx: Some(c2s_tx),
s2c_rx: Some(s2c_rx), s2c_rx: Some(s2c_rx),
@@ -56,7 +64,7 @@ struct AppState {
impl AppState { impl AppState {
pub async fn add_client(&self, peer_addr: SocketAddr) -> (Sender<Message>, Receiver<Message>) { pub async fn add_client(&self, peer_addr: SocketAddr) -> (Sender<Message>, Receiver<Message>) {
let mut client = Client::new(peer_addr); let mut client = Client::new();
let Ok((c2s_tx, s2c_rx)) = client.take_channels() else { let Ok((c2s_tx, s2c_rx)) = client.take_channels() else {
eprintln!("Unable to take channels for {}", peer_addr); eprintln!("Unable to take channels for {}", peer_addr);
unreachable!(); unreachable!();
@@ -72,6 +80,33 @@ impl AppState {
} }
} }
pub async fn user(
&self,
peer_addr: SocketAddr,
username: &str,
mode: u16,
realname: Option<&str>,
) {
if let Some(client) = self.clients.write().await.get_mut(&peer_addr) {
client.username = Some(username.to_string());
client.realname = realname.map(str::to_string)
}
}
async fn pass(&self, peer_addr: SocketAddr, _password: &str) -> bool {
if let Some(_client) = self.clients.write().await.get_mut(&peer_addr) {
return true; // client exists, there is no database rn, just return true for now
}
false
}
async fn quit(&self, peer_addr: SocketAddr, reason: Option<&str>) {
// broadcast user leaving unless invisible flag was set
self.clients.write().await.remove(&peer_addr);
}
// clients still needs mod/op status stuff // clients still needs mod/op status stuff
// join channel // join channel
@@ -106,6 +141,16 @@ impl AppState {
client.tx.send(msg).await?; client.tx.send(msg).await?;
Ok(()) Ok(())
} }
pub async fn broadcast(&self, msg: Message) -> Result<()> {
let clients = self.clients.read().await;
let addresses = clients.keys().cloned();
for peer_addr in addresses {
self.send(peer_addr, msg.clone()).await?;
}
Ok(())
}
} }
#[tokio::main] #[tokio::main]
@@ -171,6 +216,33 @@ async fn main() -> Result<()> {
} }
}); });
// Ping loop
let state: Arc<AppState> = app_state.clone();
tokio::spawn(async move {
loop {
let clients = state.clients.read().await;
for (peer_addr, client) in clients.iter() {
println!("PING :{}", client.username.clone().unwrap_or_default());
state
.send(
*peer_addr,
Message::from_str(&format!(
":localhost PING :{}",
client.username.clone().unwrap_or_default()
))?,
)
.await?;
}
drop(clients);
tokio::time::sleep(Duration::from_secs(30)).await;
}
#[allow(unreachable_code)]
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
});
tokio::signal::ctrl_c().await?; tokio::signal::ctrl_c().await?;
Ok(()) Ok(())
@@ -186,9 +258,29 @@ async fn handle(
state.send(peer_addr, Message::from_str("NONE")?).await?; state.send(peer_addr, Message::from_str("NONE")?).await?;
} }
"NICK" => { "NICK" => {
state let nick = msg.params()?.next().unwrap_or_default();
.set_nick(peer_addr, msg.params()?.next().unwrap()) state.set_nick(peer_addr, nick).await;
.await; }
"USER" => {
let mut params = msg.params()?;
let username = params.next().unwrap_or_default(); // aviinl
let mode = params.next().unwrap_or_default().parse::<u16>()?; // mode
params.next().unwrap_or_default(); // unused
let realname = msg.trailing()?; // realname
dbg!(username, realname);
state.user(peer_addr, username, mode, realname).await;
}
"PASS" => {
let mut params = msg.params()?;
let password = params.next().unwrap_or_default(); // aviinl
state.pass(peer_addr, password).await;
}
"QUIT" => {
let reason = msg.trailing()?; // realname
state.quit(peer_addr, reason).await;
} }
_ => { _ => {
return Err(format!("Unknown Command: {:?}", msg.command()?).into()); return Err(format!("Unknown Command: {:?}", msg.command()?).into());