Rewritten server code

This commit is contained in:
2026-08-29 13:27:17 +02:00
parent f315ba405a
commit 647eeec8a8
13 changed files with 671 additions and 541 deletions
+133
View File
@@ -0,0 +1,133 @@
use std::{
collections::HashMap,
sync::{Arc, atomic::AtomicU16},
};
use ed25519_dalek::VerifyingKey;
use tokio::sync::Mutex;
use crate::{
crypto::SessionCipher,
protocol::ClientMethod,
types::ClientMeta,
ws::EnclaveWebSocket,
};
pub struct UserConnections {
pub meta: ClientMeta,
pub counter: AtomicU16,
pub public_key: VerifyingKey,
pub connections: Mutex<HashMap<u16, Arc<EnclaveWebSocket>>>,
pub cipher: Arc<Mutex<SessionCipher>>,
}
pub struct SessionRegistry {
pub clients: Mutex<HashMap<VerifyingKey, Arc<UserConnections>>>,
}
impl Default for SessionRegistry {
fn default() -> Self {
Self::new()
}
}
impl SessionRegistry {
pub fn new() -> Self {
Self {
clients: Mutex::new(HashMap::new()),
}
}
pub async fn get(&self, public_key: &VerifyingKey) -> Option<Arc<UserConnections>> {
self.clients.lock().await.get(public_key).cloned()
}
/// Registers a new websocket connection for a user, returning the
/// connection and its id. The websocket is given the shared cipher
/// of the user's existing connections so voice traffic stays keyed
/// consistently across devices.
pub async fn register(
&self,
public_key: VerifyingKey,
meta: ClientMeta,
mut client: EnclaveWebSocket,
) -> (Arc<EnclaveWebSocket>, u16) {
let mut clients = self.clients.lock().await;
let user = clients
.entry(public_key)
.or_insert_with(|| {
Arc::new(UserConnections {
meta,
public_key,
counter: AtomicU16::new(0),
connections: Mutex::new(HashMap::new()),
cipher: client.cipher.clone(),
})
})
.clone();
client.cipher = user.cipher.clone();
let client = Arc::new(client);
let conid = user.counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
user.connections.lock().await.insert(conid, client.clone());
(client, conid)
}
/// Removes a connection from a user's session. Returns `true` when
/// that was the user's last connection and they have been dropped
/// from the registry entirely.
pub async fn deregister(&self, public_key: VerifyingKey, conid: u16) -> bool {
let mut clients = self.clients.lock().await;
let Some(user) = clients.get(&public_key).cloned() else {
return false;
};
let mut connections = user.connections.lock().await;
connections.remove(&conid);
if connections.is_empty() {
clients.remove(&public_key);
true
} else {
false
}
}
pub async fn broadcast(&self, message: &ClientMethod) -> anyhow::Result<()> {
let users: Vec<_> = self.clients.lock().await.values().cloned().collect();
for user in users {
if let Err(e) = user.send(message).await {
eprintln!("Failed to send to a client: {:?}", e);
}
}
Ok(())
}
}
impl UserConnections {
pub async fn send(&self, message: &ClientMethod) -> anyhow::Result<()> {
for (_, conn) in self.connections.lock().await.iter() {
conn.send(message).await?;
}
Ok(())
}
pub async fn send_to(&self, id: u16, message: &ClientMethod) -> anyhow::Result<bool> {
if let Some(conn) = self.connections.lock().await.get(&id) {
conn.send(message).await?;
Ok(true)
} else {
Ok(false)
}
}
}