use tungstenite::Message; use tungstenite::protocol::WebSocket; use tungstenite::Message::Binary; use postgres::transaction::Transaction; use std::net::{TcpStream}; use serde_cbor::{from_slice, to_vec}; use uuid::Uuid; use failure::Error; use failure::err_msg; use net::Db; use cryp::{Cryp, cryp_spawn, cryp_learn, cryp_forget}; use game::{Game, game_state, game_pve, game_pvp, game_join, game_joinable_list, game_skill, game_target}; use account::{Account, account_create, account_login, account_from_token, account_cryps}; use item::{Item, items_list, item_use}; use skill::{Skill}; pub struct Rpc; impl Rpc { pub fn receive(&self, msg: Message, db: &Db, client: &mut WebSocket) -> Result { // consume the ws data into bytes let data = msg.into_data(); // cast the msg to this type to receive method name match from_slice::(&data) { Ok(v) => { let mut tx = db.transaction()?; let account: Option = match v.token { Some(t) => Some(account_from_token(t, &mut tx)?), None => None, }; println!("{:?}", account); // now we have the method name // match on that to determine what fn to call let response = match v.method.as_ref() { "cryp_spawn" => Rpc::cryp_spawn(data, &mut tx, account, client), "cryp_learn" => Rpc::cryp_learn(data, &mut tx, account, client), "cryp_forget" => Rpc::cryp_forget(data, &mut tx, account, client), "game_state" => Rpc::game_state(data, &mut tx, account, client), "game_pve" => Rpc::game_pve(data, &mut tx, account, client), "game_pvp" => Rpc::game_pvp(data, &mut tx, account, client), "game_join" => Rpc::game_join(data, &mut tx, account, client), "game_joinable_list" => Rpc::game_joinable_list(data, &mut tx, account, client), "game_skill" => Rpc::game_skill(data, &mut tx, account, client), "game_target" => Rpc::game_target(data, &mut tx, account, client), "account_create" => Rpc::account_create(data, &mut tx, account, client), "account_login" => Rpc::account_login(data, &mut tx, account, client), "account_cryps" => Rpc::account_cryps(data, &mut tx, account, client), "item_list" => Rpc::item_list(data, &mut tx, account, client), "item_use" => Rpc::item_use(data, &mut tx, account, client), _ => Err(err_msg("unknown method")), }; tx.commit()?; return response; }, Err(_e) => Err(err_msg("invalid message")), } } fn send_msg(client: &mut WebSocket, msg: RpcResponse) -> Result<(), Error> { let bytes = to_vec(&msg)?; match client.write_message(Binary(bytes)) { Ok(()) => Ok(()), Err(e) => Err(err_msg(e)) } } fn game_state(data: Vec, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; let game_response = RpcResponse { method: "game_state".to_string(), params: RpcResult::GameState(game_state(msg.params, tx, &a)?) }; return Ok(game_response); } fn game_pve(data: Vec, tx: &mut Transaction, account: Option, client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; let game_response = RpcResponse { method: "game_state".to_string(), params: RpcResult::GameState(game_pve(msg.params, tx, &a)?) }; Rpc::send_msg(client, RpcResponse { method: "account_cryps".to_string(), params: RpcResult::CrypList(account_cryps(tx, &a)?) })?; return Ok(game_response); } fn game_pvp(data: Vec, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; let game_response = RpcResponse { method: "game_state".to_string(), params: RpcResult::GameState(game_pvp(msg.params, tx, &a)?) }; return Ok(game_response); } fn game_join(data: Vec, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; let game_response = RpcResponse { method: "game_state".to_string(), params: RpcResult::GameState(game_join(msg.params, tx, &a)?) }; return Ok(game_response); } fn game_joinable_list(_data: Vec, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; // let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; let game_list = RpcResponse { method: "game_joinable_list".to_string(), params: RpcResult::GameJoinableList(game_joinable_list(tx, &a)?) }; return Ok(game_list); } fn game_skill(data: Vec, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; let game_response = RpcResponse { method: "game_state".to_string(), params: RpcResult::GameState(game_skill(msg.params, tx, &a)?) }; // Rpc::send_msg(client, RpcResponse { // method: "account_cryps".to_string(), // params: RpcResult::CrypList(account_cryps(tx, &a)?) // })?; return Ok(game_response); } fn game_target(data: Vec, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; let game_response = RpcResponse { method: "game_state".to_string(), params: RpcResult::GameState(game_target(msg.params, tx, &a)?) }; // Rpc::send_msg(client, RpcResponse { // method: "account_cryps".to_string(), // params: RpcResult::CrypList(account_cryps(tx, &a)?) // })?; return Ok(game_response); } fn cryp_spawn(data: Vec, tx: &mut Transaction, account: Option, client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; Rpc::send_msg(client, RpcResponse { method: "cryp_spawn".to_string(), params: RpcResult::CrypSpawn(cryp_spawn(msg.params, tx, &a)?) })?; let cryp_list = RpcResponse { method: "account_cryps".to_string(), params: RpcResult::CrypList(account_cryps(tx, &a)?) }; Ok(cryp_list) } fn cryp_learn(data: Vec, tx: &mut Transaction, account: Option, client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; Rpc::send_msg(client, RpcResponse { method: "cryp_learn".to_string(), params: RpcResult::CrypLearn(cryp_learn(msg.params, tx, &a)?) })?; let cryp_list = RpcResponse { method: "account_cryps".to_string(), params: RpcResult::CrypList(account_cryps(tx, &a)?) }; Ok(cryp_list) } fn cryp_forget(data: Vec, tx: &mut Transaction, account: Option, client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; Rpc::send_msg(client, RpcResponse { method: "cryp_forget".to_string(), params: RpcResult::CrypForget(cryp_forget(msg.params, tx, &a)?) })?; let cryp_list = RpcResponse { method: "account_cryps".to_string(), params: RpcResult::CrypList(account_cryps(tx, &a)?) }; Ok(cryp_list) } fn account_create(data: Vec, tx: &mut Transaction, _account: Option, _client: &mut WebSocket) -> Result { match from_slice::(&data) { Ok(v) => Ok(RpcResponse { method: v.method, params: RpcResult::Account(account_create(v.params, tx)?) }), Err(_e) => Err(err_msg("invalid params")), } } fn account_login(data: Vec, tx: &mut Transaction, _account: Option, _client: &mut WebSocket) -> Result { match from_slice::(&data) { Ok(v) => Ok(RpcResponse { method: v.method, params: RpcResult::Account(account_login(v.params, tx)?) }), Err(_e) => Err(err_msg("invalid params")), } } fn account_cryps(_data: Vec, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result { match account { Some(a) => Ok(RpcResponse { method: "account_cryps".to_string(), params: RpcResult::CrypList(account_cryps(tx, &a)?) }), None => Err(err_msg("auth required")), } } fn item_list(_data: Vec, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result { match account { Some(a) => Ok(RpcResponse { method: "item_list".to_string(), params: RpcResult::ItemList(items_list(tx, &a)?) }), None => Err(err_msg("auth required")), } } fn item_use(data: Vec, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result { let a = match account { Some(a) => a, None => return Err(err_msg("auth required")), }; let msg = from_slice::(&data).or(Err(err_msg("invalid params")))?; item_use(msg.params, tx, &a)?; let cryps_list = RpcResponse { method: "account_cryps".to_string(), params: RpcResult::CrypList(account_cryps(tx, &a)?) }; return Ok(cryps_list); } } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct RpcResponse { method: String, params: RpcResult, } #[derive(Debug,Clone,Serialize,Deserialize)] pub enum RpcResult { CrypSpawn(Cryp), CrypForget(Cryp), CrypLearn(Cryp), Account(Account), CrypList(Vec), GameState(Game), GameJoinableList(Vec), ItemList(Vec), ItemUse(()), } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct RpcMessage { method: String, token: Option, } #[derive(Debug,Clone,Serialize,Deserialize)] struct CrypSpawnMsg { method: String, params: CrypSpawnParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct CrypSpawnParams { pub name: String, } #[derive(Debug,Clone,Serialize,Deserialize)] struct CrypLearnMsg { method: String, params: CrypLearnParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct CrypLearnParams { pub id: Uuid, pub skill: Skill, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct CrypForgetParams { pub id: Uuid, pub skill: Skill, } #[derive(Debug,Clone,Serialize,Deserialize)] struct CrypForgetMsg { method: String, params: CrypForgetParams, } #[derive(Debug,Clone,Serialize,Deserialize)] struct GameStateMsg { method: String, params: GameStateParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct GameStateParams { pub id: Uuid, } #[derive(Debug,Clone,Serialize,Deserialize)] struct GamePveMsg { method: String, params: GamePveParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct GamePveParams { pub cryp_ids: Vec, } #[derive(Debug,Clone,Serialize,Deserialize)] struct GamePvpMsg { method: String, params: GamePvpParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct GamePvpParams { pub cryp_ids: Vec, } #[derive(Debug,Clone,Serialize,Deserialize)] struct GameJoinMsg { method: String, params: GameJoinParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct GameJoinParams { pub game_id: Uuid, pub cryp_ids: Vec, } #[derive(Debug,Clone,Serialize,Deserialize)] struct GameJoinableListMsg { method: String, params: (), } #[derive(Debug,Clone,Serialize,Deserialize)] struct GameTargetMsg { method: String, params: GameTargetParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct GameTargetParams { pub game_id: Uuid, pub cryp_id: Uuid, pub skill_id: Uuid, } #[derive(Debug,Clone,Serialize,Deserialize)] struct GameSkillMsg { method: String, params: GameSkillParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct GameSkillParams { pub game_id: Uuid, pub cryp_id: Uuid, pub target_team_id: Option, pub skill: Skill, } #[derive(Debug,Clone,Serialize,Deserialize)] struct AccountCreateMsg { method: String, params: AccountCreateParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct AccountCreateParams { pub name: String, pub password: String, } #[derive(Debug,Clone,Serialize,Deserialize)] struct AccountLoginMsg { method: String, params: AccountLoginParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct AccountLoginParams { pub name: String, pub password: String, } #[derive(Debug,Clone,Serialize,Deserialize)] struct AccountCrypsMsg { method: String, params: (), } #[derive(Debug,Clone,Serialize,Deserialize)] struct ItemListMsg { method: String, params: (), } #[derive(Debug,Clone,Serialize,Deserialize)] struct ItemUseMsg { method: String, params: ItemUseParams, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct ItemUseParams { pub item: Uuid, pub target: Uuid, } // #[cfg(test)] // mod tests { // use super::*; // use serde_cbor::to_vec; // #[test] // fn rpc_parse() { // let rpc = Rpc {}; // let msg = GenerateMsg { method: "cryp_generate".to_string(), params: GenerateParams { level: 64 } }; // let v = to_vec(&msg).unwrap(); // let received = rpc.receive(Message::Binary(v)); // } // }