mnml/server/src/rpc.rs
2018-11-22 12:11:16 +11:00

530 lines
16 KiB
Rust
Executable File

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<TcpStream>) -> Result<RpcResponse, Error> {
// consume the ws data into bytes
let data = msg.into_data();
// cast the msg to this type to receive method name
match from_slice::<RpcMessage>(&data) {
Ok(v) => {
let mut tx = db.transaction()?;
let account: Option<Account> = 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<TcpStream>, 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<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<GameStateMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<GamePveMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<GamePvpMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<GameJoinMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
// let msg = from_slice::<GameJoinMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<GameSkillMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<GameTargetMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<CrypSpawnMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<CrypLearnMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<CrypForgetMsg>(&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<u8>, tx: &mut Transaction, _account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
match from_slice::<AccountCreateMsg>(&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<u8>, tx: &mut Transaction, _account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
match from_slice::<AccountLoginMsg>(&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<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
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<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
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<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<ItemUseMsg>(&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<Cryp>),
GameState(Game),
GameJoinableList(Vec<Game>),
ItemList(Vec<Item>),
ItemUse(()),
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct RpcMessage {
method: String,
token: Option<String>,
}
#[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<Uuid>,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
struct GamePvpMsg {
method: String,
params: GamePvpParams,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct GamePvpParams {
pub cryp_ids: Vec<Uuid>,
}
#[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<Uuid>,
}
#[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<Uuid>,
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));
// }
// }