on and offline users

This commit is contained in:
Adam 2024-07-31 21:19:29 -04:00
parent 8315b7041a
commit a6681f31a0
4 changed files with 117 additions and 43 deletions

33
Cargo.lock generated
View file

@ -226,9 +226,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.6.1" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" checksum = "fca2be1d5c43812bae364ee3f30b3afcb7877cf59f4aeb94c66f313a41d2fac9"
[[package]] [[package]]
name = "camino" name = "camino"
@ -838,9 +838,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.6" version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
@ -1371,12 +1371,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.19" version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2288c0e17cc8d342c712bb43a257a80ebffce59cdb33d5000d8348f3ec02528b" checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f"
dependencies = [ dependencies = [
"zerocopy", "zerocopy",
"zerocopy-derive",
] ]
[[package]] [[package]]
@ -2057,9 +2056,9 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.17" version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a44eede9b727419af8095cb2d72fab15487a541f54647ad4414b34096ee4631" checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
@ -2078,9 +2077,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.18" version = "0.22.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1490595c74d930da779e944f5ba2ecdf538af67df1a9848cbd156af43c1b7cf0" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"serde", "serde",
@ -2571,9 +2570,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.16" version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -2592,9 +2591,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.7.35" version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"zerocopy-derive", "zerocopy-derive",
@ -2602,9 +2601,9 @@ dependencies = [
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.7.35" version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -27,7 +27,7 @@ fn motd() -> String {
/// Generate server summary update - mostly debug stuff /// Generate server summary update - mostly debug stuff
fn server_summary_update(state: &Arc<AppState>) -> String { fn server_summary_update(state: &Arc<AppState>) -> String {
to_string::<ServerStateSummary>(&ServerStateSummary { to_string::<ServerStateSummary>(&ServerStateSummary {
online_users: state.users.lock().unwrap().len(), online_users: state.online_users.lock().unwrap().len(),
active_games: state.games.lock().unwrap().len(), active_games: state.games.lock().unwrap().len(),
}) })
.unwrap() .unwrap()
@ -38,7 +38,7 @@ fn chat_meta_update(state: &Arc<AppState>) -> String {
// this may get expensive if there are many users // this may get expensive if there are many users
let mut names = vec![]; let mut names = vec![];
for user in state.users.lock().unwrap().iter() { for user in state.online_users.lock().unwrap().iter() {
names.push(user.1.name.clone()); names.push(user.1.name.clone());
} }
@ -65,7 +65,7 @@ fn games_update(state: &Arc<AppState>) -> String {
fn announce_join(state: &Arc<AppState>, addr: &SocketAddr) -> String { fn announce_join(state: &Arc<AppState>, addr: &SocketAddr) -> String {
let msg = format!( let msg = format!(
"{} joined.", "{} joined.",
state.users.lock().unwrap().get(addr).unwrap().name state.online_users.lock().unwrap().get(addr).unwrap().name
); );
tracing::debug!("{}", &msg); tracing::debug!("{}", &msg);
@ -98,7 +98,9 @@ async fn handle_new_user(
addr: &SocketAddr, addr: &SocketAddr,
) -> Result<()> { ) -> Result<()> {
// Create // Create
let new_user = generate_new_user(state); let new_user = Box::pin(generate_new_user(state));
tracing::debug!("User created at ptr: {:p}", new_user);
tracing::debug!("User borrowed ptr: {:p}", *&new_user);
// Notify client of new username // Notify client of new username
sender sender
@ -106,7 +108,9 @@ async fn handle_new_user(
.await?; .await?;
// Register using `addr` as key until something longer lived exists // Register using `addr` as key until something longer lived exists
state.users.lock().unwrap().insert(*addr, new_user); state.online_users.lock().unwrap().insert(*addr, new_user);
tracing::debug!("New user inserted at ptr: {:p}", state.online_users.lock().unwrap().get(addr).unwrap());
tracing::debug!("New user hashmap deref ptr: {:p}", *state.online_users.lock().unwrap().get(addr).unwrap());
// Hydrate client // Hydrate client
// this should probably be combined and sent as one // this should probably be combined and sent as one

View file

@ -39,7 +39,7 @@ fn handle_chat_message(
tx: &Sender<String>, tx: &Sender<String>,
addr: SocketAddr, addr: SocketAddr,
) -> Result<()> { ) -> Result<()> {
let msg = format! {"{0}: {1}", state.users.lock().unwrap().get(&addr).unwrap().name, chat_message.text}; let msg = format! {"{0}: {1}", state.online_users.lock().unwrap().get(&addr).unwrap().name, chat_message.text};
tracing::debug!("{msg}"); tracing::debug!("{msg}");
tx.send(to_string::<ChatMessage>(&ChatMessage { text: msg })?)?; tx.send(to_string::<ChatMessage>(&ChatMessage { text: msg })?)?;
@ -53,11 +53,42 @@ fn handle_user_log_in(
tx: &Sender<String>, tx: &Sender<String>,
addr: SocketAddr, addr: SocketAddr,
) -> Result<()> { ) -> Result<()> {
let old_name = state.users.lock().unwrap().get(&addr).unwrap().name.clone(); let old_name = state
.online_users
.lock()
.unwrap()
.get(&addr)
.unwrap()
.name
.clone();
let new_name = user_log_in.username.clone(); let new_name = user_log_in.username.clone();
if state.offline_users.lock().unwrap().contains_key(&new_name) {
state state
.users .online_users
.lock()
.unwrap()
.insert(
addr,
state
.offline_users
.lock()
.unwrap()
.remove(&new_name)
.unwrap(),
)
.unwrap();
let msg = format! {
"{0} changed name to {1}. Welcome back!",
old_name,
new_name
};
tracing::debug!("{msg}");
} else {
state
.online_users
.lock() .lock()
.unwrap() .unwrap()
.get_mut(&addr) .get_mut(&addr)
@ -72,6 +103,21 @@ fn handle_user_log_in(
tracing::debug!("{msg}"); tracing::debug!("{msg}");
tx.send(to_string::<ChatMessage>(&ChatMessage { text: msg })?)?; tx.send(to_string::<ChatMessage>(&ChatMessage { text: msg })?)?;
}
tracing::debug!(
"User updated at ptr: {:p}",
state.online_users.lock().unwrap().get(&addr).unwrap()
);
tracing::debug!(
"User updated deref ptr: {:p}",
*state.online_users.lock().unwrap().get(&addr).unwrap()
);
tracing::debug!(
"Online Users: {} Offline Users: {}",
state.online_users.lock().unwrap().len(),
state.offline_users.lock().unwrap().len()
);
Ok(()) Ok(())
} }
@ -86,7 +132,7 @@ fn handle_close(
if let Some(cf) = close_frame { if let Some(cf) = close_frame {
tracing::debug!( tracing::debug!(
"Close received from {0} with code: {1} and reason: {2}", "Close received from {0} with code: {1} and reason: {2}",
state.users.lock().unwrap().get(&addr).unwrap().name, state.online_users.lock().unwrap().get(&addr).unwrap().name,
cf.code, cf.code,
cf.reason cf.reason
) )
@ -97,13 +143,34 @@ fn handle_close(
let msg = ChatMessage { let msg = ChatMessage {
text: format!( text: format!(
"{0} left.", "{0} left.",
state.users.lock().unwrap().get(&addr).unwrap().name state.online_users.lock().unwrap().get(&addr).unwrap().name
), ),
}; };
tracing::debug!("{}", msg.text); tracing::debug!("{}", msg.text);
tx.send(to_string::<ChatMessage>(&msg)?)?; tx.send(to_string::<ChatMessage>(&msg)?)?;
state.users.lock().unwrap().remove(&addr).unwrap(); let name = state
.online_users
.lock()
.unwrap()
.get(&addr)
.unwrap()
.name
.clone();
state.offline_users.lock().unwrap().insert(
name.clone(),
state.online_users.lock().unwrap().remove(&addr).unwrap(),
);
tracing::debug!(
"User moved to offline ptr: {:p}",
state.offline_users.lock().unwrap().get(&name).unwrap()
);
tracing::debug!(
"User offline deref ptr: {:p}",
*state.offline_users.lock().unwrap().get(&name).unwrap()
);
tx.send(server_summary_update(state))?; tx.send(server_summary_update(state))?;
tx.send(chat_meta_update(state))?; tx.send(chat_meta_update(state))?;

View file

@ -8,6 +8,7 @@ use std::{
fs::{read_to_string, File}, fs::{read_to_string, File},
io::{BufRead, BufReader}, io::{BufRead, BufReader},
net::SocketAddr, net::SocketAddr,
pin::Pin,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use tokio::sync::broadcast; use tokio::sync::broadcast;
@ -43,7 +44,8 @@ fn load_names(path: &str) -> Result<Vec<String>> {
// Our shared state // Our shared state
pub struct AppState { pub struct AppState {
// We require unique usernames. This tracks which usernames have been taken. // We require unique usernames. This tracks which usernames have been taken.
users: Mutex<HashMap<SocketAddr, User>>, online_users: Mutex<HashMap<SocketAddr, Pin<Box<User>>>>,
offline_users: Mutex<HashMap<String, Pin<Box<User>>>>,
// Channel used to send messages to all connected clients. // Channel used to send messages to all connected clients.
tx: broadcast::Sender<String>, tx: broadcast::Sender<String>,
// Master card decks // Master card decks
@ -67,14 +69,16 @@ async fn main() -> Result<()> {
// Set up application state for use with with_state(). // Set up application state for use with with_state().
let (tx, _rx) = broadcast::channel(100); let (tx, _rx) = broadcast::channel(100);
let users = Mutex::new(HashMap::<SocketAddr, User>::new()); let online_users = Mutex::new(HashMap::<SocketAddr, Pin<Box<User>>>::new());
let offline_users = Mutex::new(HashMap::<String, Pin<Box<User>>>::new());
let all_cards = load_cards_from_json("data/cah-cards-full.json")?; let all_cards = load_cards_from_json("data/cah-cards-full.json")?;
let games = Mutex::new(vec![]); let games = Mutex::new(vec![]);
let first_names = load_names("data/first.txt")?; let first_names = load_names("data/first.txt")?;
let last_names = load_names("data/last.txt")?; let last_names = load_names("data/last.txt")?;
let app_state = Arc::new(AppState { let app_state = Arc::new(AppState {
users, online_users,
offline_users,
tx, tx,
all_cards, all_cards,
games, games,