message handler
This commit is contained in:
parent
4fa78181c7
commit
33d81fd316
3 changed files with 71 additions and 63 deletions
55
src/api.rs
55
src/api.rs
|
@ -1,16 +1,17 @@
|
||||||
use crate::gamemaster::*;
|
use crate::gamemaster::*;
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
use axum::extract::ConnectInfo;
|
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{
|
extract::{
|
||||||
ws::{Message, WebSocket, WebSocketUpgrade},
|
ws::{Message, WebSocket, WebSocketUpgrade},
|
||||||
State,
|
ConnectInfo, State,
|
||||||
},
|
},
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
};
|
};
|
||||||
use futures::{sink::SinkExt, stream::StreamExt};
|
use futures::{sink::SinkExt, stream::StreamExt};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{net::SocketAddr, sync::Arc};
|
use std::{net::SocketAddr, sync::Arc};
|
||||||
|
pub mod message_handler;
|
||||||
|
use crate::message_handler::*;
|
||||||
|
|
||||||
/// New game request structure
|
/// New game request structure
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -51,6 +52,7 @@ fn greeting(state: &Arc<AppState>) -> String {
|
||||||
state.games.lock().unwrap().len(),
|
state.games.lock().unwrap().len(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn websocket(stream: WebSocket, state: Arc<AppState>, who: SocketAddr) {
|
pub async fn websocket(stream: WebSocket, state: Arc<AppState>, who: SocketAddr) {
|
||||||
// By splitting, we can send and receive at the same time.
|
// By splitting, we can send and receive at the same time.
|
||||||
let (mut sender, mut receiver) = stream.split();
|
let (mut sender, mut receiver) = stream.split();
|
||||||
|
@ -74,57 +76,10 @@ pub async fn websocket(stream: WebSocket, state: Arc<AppState>, who: SocketAddr)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// clone things for receiving task
|
|
||||||
let tx = state.tx.clone();
|
|
||||||
let name = who.clone();
|
|
||||||
|
|
||||||
// handle new incoming messages
|
// handle new incoming messages
|
||||||
let mut recv_task = tokio::spawn(async move {
|
let mut recv_task = tokio::spawn(async move {
|
||||||
while let Some(Ok(message)) = receiver.next().await {
|
while let Some(Ok(message)) = receiver.next().await {
|
||||||
match message {
|
message_handler(message, &state, who).await
|
||||||
Message::Text(text) => {
|
|
||||||
tracing::debug!("{who}: {}", text);
|
|
||||||
|
|
||||||
if let Ok(new_game) = serde_json::from_str::<NewGameRequest>(&text) {
|
|
||||||
tracing::debug!("{:#?}", &new_game);
|
|
||||||
// create game
|
|
||||||
if let Ok(new_game_object) = CAHGame::new(new_game) {
|
|
||||||
state.games.lock().unwrap().push(new_game_object);
|
|
||||||
let _update = tx.send(greeting(&state));
|
|
||||||
} else {
|
|
||||||
let _res = tx.send(format!("error creating game"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// just echo
|
|
||||||
let msg = format!{"{who}: {text}"};
|
|
||||||
tracing::debug!("{msg}");
|
|
||||||
let _res = tx.send(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Message::Binary(data) => {
|
|
||||||
tracing::debug!("Binary: {:?}", data)
|
|
||||||
}
|
|
||||||
Message::Close(c) => {
|
|
||||||
if let Some(cf) = c {
|
|
||||||
tracing::debug!(
|
|
||||||
"Close received from {who} with code: {} and reason: {}",
|
|
||||||
cf.code,
|
|
||||||
cf.reason
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
tracing::debug!("close received without close frame")
|
|
||||||
}
|
|
||||||
let msg = format!("{name} left.");
|
|
||||||
tracing::debug!("{msg}");
|
|
||||||
let _ = tx.send(msg);
|
|
||||||
}
|
|
||||||
Message::Pong(ping) => {
|
|
||||||
tracing::debug!("Pong received with: {:?}", ping);
|
|
||||||
}
|
|
||||||
Message::Ping(pong) => {
|
|
||||||
tracing::debug!("Pong received with: {:?}", pong);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
58
src/api/message_handler.rs
Normal file
58
src/api/message_handler.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::api::{greeting, Message, SocketAddr};
|
||||||
|
use crate::AppState;
|
||||||
|
use crate::Arc;
|
||||||
|
use crate::CAHGame;
|
||||||
|
use crate::NewGameRequest;
|
||||||
|
|
||||||
|
pub async fn message_handler(message: Message, state: &Arc<AppState>, who: SocketAddr) {
|
||||||
|
let tx = &state.tx;
|
||||||
|
|
||||||
|
match message {
|
||||||
|
Message::Text(text) => {
|
||||||
|
tracing::debug!("{who}: {}", text);
|
||||||
|
|
||||||
|
if let Ok(new_game) = serde_json::from_str::<NewGameRequest>(&text) {
|
||||||
|
tracing::debug!("{:#?}", &new_game);
|
||||||
|
// create game
|
||||||
|
if let Ok(new_game_object) = CAHGame::new(new_game) {
|
||||||
|
state.games.lock().unwrap().push(new_game_object);
|
||||||
|
let _update = tx.send(greeting(&state));
|
||||||
|
} else {
|
||||||
|
let _res = tx.send(format!("error creating game"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// just echo
|
||||||
|
let msg = format! {"{who}: {text}"};
|
||||||
|
tracing::debug!("{msg}");
|
||||||
|
let _res = tx.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Binary(data) => {
|
||||||
|
tracing::debug!("Binary: {:?}", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Close(c) => {
|
||||||
|
if let Some(cf) = c {
|
||||||
|
tracing::debug!(
|
||||||
|
"Close received from {who} with code: {} and reason: {}",
|
||||||
|
cf.code,
|
||||||
|
cf.reason
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
tracing::debug!("close received without close frame")
|
||||||
|
}
|
||||||
|
let msg = format!("{who} left.");
|
||||||
|
tracing::debug!("{msg}");
|
||||||
|
let _ = tx.send(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Pong(ping) => {
|
||||||
|
tracing::debug!("Pong received with: {:?}", ping);
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::Ping(pong) => {
|
||||||
|
tracing::debug!("Pong received with: {:?}", pong);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
src/main.rs
21
src/main.rs
|
@ -1,16 +1,16 @@
|
||||||
use axum::{response::Html, routing::get, Router, ServiceExt};
|
use axum::{response::Html, routing::get, Router};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
// collections::HashSet,
|
||||||
|
error::Error,
|
||||||
|
fs,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
|
result::Result,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
use std::{error::Error, fs, result::Result};
|
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
pub mod gamemaster;
|
pub mod gamemaster;
|
||||||
use crate::gamemaster::*;
|
use crate::gamemaster::*;
|
||||||
|
|
||||||
pub mod api;
|
pub mod api;
|
||||||
use crate::api::*;
|
use crate::api::*;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ fn test() -> Result<(), Box<dyn Error>> {
|
||||||
// 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.
|
||||||
user_set: Mutex<HashSet<String>>,
|
// user_set: Mutex<HashSet<String>>,
|
||||||
// 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
|
||||||
|
@ -96,18 +96,13 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
// Set up application state for use with with_state().
|
// Set up application state for use with with_state().
|
||||||
let user_set = Mutex::new(HashSet::new());
|
// let user_set = Mutex::new(HashSet::new());
|
||||||
let (tx, _rx) = broadcast::channel(100);
|
let (tx, _rx) = broadcast::channel(100);
|
||||||
|
|
||||||
// choose decks
|
|
||||||
let cards_input_path: &str = "data/cah-cards-full.json";
|
let cards_input_path: &str = "data/cah-cards-full.json";
|
||||||
|
|
||||||
// TODO: this should be a master card database and pointers
|
|
||||||
// to the cards should be passed to the game instead of actual cards
|
|
||||||
let all_cards = Mutex::new(load_json(cards_input_path)?);
|
let all_cards = Mutex::new(load_json(cards_input_path)?);
|
||||||
let games = Mutex::new(vec![]);
|
let games = Mutex::new(vec![]);
|
||||||
let app_state = Arc::new(AppState {
|
let app_state = Arc::new(AppState {
|
||||||
user_set,
|
// user_set,
|
||||||
tx,
|
tx,
|
||||||
all_cards,
|
all_cards,
|
||||||
games,
|
games,
|
||||||
|
|
Loading…
Add table
Reference in a new issue