ping no worky
This commit is contained in:
110
src/main.rs
110
src/main.rs
@@ -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());
|
||||||
|
Reference in New Issue
Block a user