Message broadcast
This commit is contained in:
@@ -45,6 +45,12 @@ pub async fn send_message(
|
|||||||
|
|
||||||
server.message_store.insert_message(&channel_id, &stored)?;
|
server.message_store.insert_message(&channel_id, &stored)?;
|
||||||
|
|
||||||
|
server
|
||||||
|
.broadcast(&ClientMethod::Messages {
|
||||||
|
messages: HashMap::from([(channel_id, vec![stored])]),
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+42
-13
@@ -9,7 +9,7 @@ use axum::{
|
|||||||
response::Response,
|
response::Response,
|
||||||
};
|
};
|
||||||
use ed25519_dalek::{SigningKey, VerifyingKey};
|
use ed25519_dalek::{SigningKey, VerifyingKey};
|
||||||
use tokio::sync::Mutex;
|
use tokio::{sync::Mutex, task::JoinSet};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{config::Config, messages::MessageStore},
|
data::{config::Config, messages::MessageStore},
|
||||||
@@ -21,13 +21,13 @@ pub struct UserConnections {
|
|||||||
pub meta: ClientMeta,
|
pub meta: ClientMeta,
|
||||||
pub counter: AtomicU16,
|
pub counter: AtomicU16,
|
||||||
pub public_key: VerifyingKey,
|
pub public_key: VerifyingKey,
|
||||||
pub connections: HashMap<u16, Arc<Mutex<WebSocket>>>,
|
pub connections: Mutex<HashMap<u16, Arc<Mutex<WebSocket>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
pub key: SigningKey,
|
pub key: SigningKey,
|
||||||
pub config: Config,
|
pub config: Config,
|
||||||
pub clients: Mutex<HashMap<VerifyingKey, UserConnections>>,
|
pub clients: Mutex<HashMap<VerifyingKey, Arc<UserConnections>>>,
|
||||||
pub message_store: MessageStore,
|
pub message_store: MessageStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,21 +53,27 @@ impl Server {
|
|||||||
|
|
||||||
let mut clients_meta = s.clients.lock().await;
|
let mut clients_meta = s.clients.lock().await;
|
||||||
|
|
||||||
let clients =
|
let clients = clients_meta
|
||||||
clients_meta
|
|
||||||
.entry(public_key)
|
.entry(public_key)
|
||||||
.or_insert_with(|| UserConnections {
|
.or_insert_with(|| {
|
||||||
|
Arc::new(UserConnections {
|
||||||
meta,
|
meta,
|
||||||
public_key: public_key,
|
public_key: public_key,
|
||||||
counter: AtomicU16::new(0),
|
counter: AtomicU16::new(0),
|
||||||
connections: HashMap::new(),
|
connections: Mutex::new(HashMap::new()),
|
||||||
});
|
})
|
||||||
|
})
|
||||||
|
.clone();
|
||||||
|
|
||||||
let conid = clients
|
let conid = clients
|
||||||
.counter
|
.counter
|
||||||
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
clients.connections.insert(conid, client.clone());
|
clients
|
||||||
|
.connections
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.insert(conid, client.clone());
|
||||||
|
|
||||||
if let Err(e) = read_loop(&s, public_key, &client).await {
|
if let Err(e) = read_loop(&s, public_key, &client).await {
|
||||||
eprintln!("Failed to handle client: {e}");
|
eprintln!("Failed to handle client: {e}");
|
||||||
@@ -75,9 +81,11 @@ impl Server {
|
|||||||
println!("Client connection closed")
|
println!("Client connection closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
clients.connections.remove(&conid);
|
let mut connections = clients.connections.lock().await;
|
||||||
|
|
||||||
if clients.connections.len() == 0 {
|
connections.remove(&conid);
|
||||||
|
|
||||||
|
if connections.len() == 0 {
|
||||||
clients_meta.remove(&public_key);
|
clients_meta.remove(&public_key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,11 +96,32 @@ impl Server {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn broadcast(self: &Arc<Self>, message: &ClientMethod) -> anyhow::Result<()> {
|
||||||
|
let mut set = JoinSet::new();
|
||||||
|
|
||||||
|
for (_, client) in self.clients.lock().await.iter() {
|
||||||
|
let msg = message.clone();
|
||||||
|
let client = client.clone();
|
||||||
|
|
||||||
|
set.spawn(async move { client.send(&msg).await });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Await all spawned tasks to finish
|
||||||
|
while let Some(res) = set.join_next().await {
|
||||||
|
// handle task panic or errors if necessary
|
||||||
|
if let Ok(Err(e)) = res {
|
||||||
|
eprintln!("Failed to send to a client: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserConnections {
|
impl UserConnections {
|
||||||
pub async fn send(&self, message: &ClientMethod) -> anyhow::Result<()> {
|
pub async fn send(&self, message: &ClientMethod) -> anyhow::Result<()> {
|
||||||
for (_, conn) in &self.connections {
|
for (_, conn) in self.connections.lock().await.iter() {
|
||||||
send_socket(&mut *conn.lock().await, message).await?;
|
send_socket(&mut *conn.lock().await, message).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +129,7 @@ impl UserConnections {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_to(&self, id: u16, message: &ClientMethod) -> anyhow::Result<bool> {
|
pub async fn send_to(&self, id: u16, message: &ClientMethod) -> anyhow::Result<bool> {
|
||||||
if let Some(conn) = self.connections.get(&id) {
|
if let Some(conn) = self.connections.lock().await.get(&id) {
|
||||||
send_socket(&mut *conn.lock().await, message).await?;
|
send_socket(&mut *conn.lock().await, message).await?;
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
|||||||
Reference in New Issue
Block a user