YEH
This commit is contained in:
parent
a77bec2c9f
commit
be7a388812
@ -3,13 +3,6 @@ name = "mnml"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["ntr <ntr@smokestack.io>"]
|
authors = ["ntr <ntr@smokestack.io>"]
|
||||||
|
|
||||||
# makes sure to include openssl links in runtime path
|
|
||||||
# [profile.release]
|
|
||||||
# rpath = true
|
|
||||||
|
|
||||||
# [profile.dev]
|
|
||||||
# rpath = true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = "1"
|
serde = "1"
|
||||||
serde_derive = "1"
|
serde_derive = "1"
|
||||||
@ -38,10 +31,9 @@ persistent = "0.4"
|
|||||||
router = "0.6"
|
router = "0.6"
|
||||||
cookie = "0.12"
|
cookie = "0.12"
|
||||||
tungstenite = "0.8"
|
tungstenite = "0.8"
|
||||||
|
tokio-tungstenite = "0.8"
|
||||||
|
futures = "0.1"
|
||||||
|
tokio = "0.1"
|
||||||
crossbeam-channel = "0.3"
|
crossbeam-channel = "0.3"
|
||||||
|
|
||||||
stripe-rust = { version = "0.10.4", features = ["webhooks"] }
|
stripe-rust = { version = "0.10.4", features = ["webhooks"] }
|
||||||
|
|
||||||
# [patch.crates-io]
|
|
||||||
# stripe-rust = { git = "https://github.com/margh/stripe-rs.git" }
|
|
||||||
|
|
||||||
|
|||||||
@ -144,3 +144,100 @@ pub fn start(pool: PgPool, mut events: Events) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #[derive(Debug)]
|
||||||
|
// struct Subscriptions {
|
||||||
|
// account: Option<Uuid>,
|
||||||
|
// game: Option<Uuid>,
|
||||||
|
// instance: Option<Uuid>,
|
||||||
|
// // account_instances: Vec<Uuid>,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl Subscriptions {
|
||||||
|
// fn new(ws_pool: &PgPool, account: &Option<Account>, ws: &mut Ws) -> Result<Subscriptions, Error> {
|
||||||
|
// if let Some(a) = account {
|
||||||
|
// let db = ws_pool.get()?;
|
||||||
|
// let mut tx = db.transaction()?;
|
||||||
|
|
||||||
|
// // send account constructs
|
||||||
|
// let account_constructs = account::account_constructs(&mut tx, a)?;
|
||||||
|
// ws.client.write_message(Binary(to_vec(&rpc::RpcMessage::AccountConstructs(account_constructs))?))?;
|
||||||
|
|
||||||
|
// // get account instances
|
||||||
|
// // and send them to the client
|
||||||
|
// let account_instances = account::account_instances(&mut tx, a)?;
|
||||||
|
// // let instances = account_instances.iter().map(|i| i.id).collect::<Vec<Uuid>>();
|
||||||
|
// ws.client.write_message(Binary(to_vec(&rpc::RpcMessage::AccountInstances(account_instances))?))?;
|
||||||
|
|
||||||
|
// // get players
|
||||||
|
// // add to games
|
||||||
|
// tx.commit()?;
|
||||||
|
|
||||||
|
// return Ok(Subscriptions {
|
||||||
|
// account: Some(a.id),
|
||||||
|
// game: None,
|
||||||
|
// instance: None,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Ok(Subscriptions {
|
||||||
|
// account: None,
|
||||||
|
// game: None,
|
||||||
|
// instance: None
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn update(&mut self, msg: &RpcMessage) -> Result<&mut Subscriptions, Error> {
|
||||||
|
// match msg {
|
||||||
|
// RpcMessage::AccountState(a) => self.account = Some(a.id),
|
||||||
|
// RpcMessage::InstanceState(i) => self.instance = Some(i.id),
|
||||||
|
// RpcMessage::GameState(g) => self.game = Some(g.id),
|
||||||
|
// _ => (),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // info!("subscriptions updated {:?}", self);
|
||||||
|
|
||||||
|
// Ok(self)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// fn handle_message(subs: &Subscriptions, m: Message, ws: &mut Ws) {
|
||||||
|
// if let Some(msg) = match m {
|
||||||
|
// Message::Account(a) => {
|
||||||
|
// match subs.account {
|
||||||
|
// Some(wsa) => match wsa == a.id {
|
||||||
|
// true => Some(rpc::RpcMessage::AccountState(a)),
|
||||||
|
// false => None,
|
||||||
|
// },
|
||||||
|
// None => None,
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// Message::Instance(i) => {
|
||||||
|
// match subs.instance {
|
||||||
|
// Some(ci) => match ci == i.id {
|
||||||
|
// true => Some(rpc::RpcMessage::InstanceState(i)),
|
||||||
|
// false => None,
|
||||||
|
// },
|
||||||
|
// None => None,
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// Message::Game(g) => {
|
||||||
|
// match subs.game {
|
||||||
|
// Some(cg) => match cg == g.id {
|
||||||
|
// true => Some(rpc::RpcMessage::GameState(g)),
|
||||||
|
// false => None,
|
||||||
|
// },
|
||||||
|
// None => None,
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// Message::Connect(tx) => {
|
||||||
|
// info!("client connected {:?}", tx);
|
||||||
|
// None
|
||||||
|
// },
|
||||||
|
// // _ => None,
|
||||||
|
// } {
|
||||||
|
// ws.client.write_message(Binary(to_vec(&msg).unwrap())).unwrap();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@ -24,7 +24,13 @@ extern crate bodyparser;
|
|||||||
extern crate persistent;
|
extern crate persistent;
|
||||||
extern crate router;
|
extern crate router;
|
||||||
extern crate cookie;
|
extern crate cookie;
|
||||||
|
|
||||||
|
extern crate futures;
|
||||||
|
extern crate tokio;
|
||||||
|
|
||||||
|
extern crate tokio_tungstenite;
|
||||||
extern crate tungstenite;
|
extern crate tungstenite;
|
||||||
|
|
||||||
extern crate crossbeam_channel;
|
extern crate crossbeam_channel;
|
||||||
|
|
||||||
mod account;
|
mod account;
|
||||||
@ -54,6 +60,8 @@ use std::thread::{sleep, spawn};
|
|||||||
use std::time::{Duration};
|
use std::time::{Duration};
|
||||||
use std::path::{Path};
|
use std::path::{Path};
|
||||||
|
|
||||||
|
use futures::Future;
|
||||||
|
|
||||||
use events::{start as events_start};
|
use events::{start as events_start};
|
||||||
use warden::warden;
|
use warden::warden;
|
||||||
|
|
||||||
@ -104,6 +112,9 @@ fn main() {
|
|||||||
|
|
||||||
// this should go on a thread too?
|
// this should go on a thread too?
|
||||||
let ws_pool = pool.clone();
|
let ws_pool = pool.clone();
|
||||||
ws::start(ws_pool, events);
|
let wsf = ws::start(ws_pool, events);
|
||||||
|
|
||||||
|
tokio::runtime::run(wsf.map_err(|_e| ()));
|
||||||
|
|
||||||
info!("server started");
|
info!("server started");
|
||||||
}
|
}
|
||||||
|
|||||||
259
server/src/ws.rs
259
server/src/ws.rs
@ -1,26 +1,27 @@
|
|||||||
use std::time::{Instant};
|
use std::time::{Instant};
|
||||||
use std::net::{TcpStream, TcpListener};
|
|
||||||
use std::thread::{spawn};
|
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use cookie::Cookie;
|
use cookie::Cookie;
|
||||||
|
|
||||||
|
use futures::stream::Stream;
|
||||||
|
use futures::Future;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
use tungstenite::Message::Binary;
|
use tungstenite::Message::Binary;
|
||||||
use tungstenite::handshake::server::{Request, ErrorResponse};
|
use tungstenite::handshake::server::{Request, ErrorResponse};
|
||||||
use tungstenite::handshake::HandshakeRole;
|
use tungstenite::handshake::HandshakeRole;
|
||||||
use tungstenite::http::StatusCode;
|
use tungstenite::http::StatusCode;
|
||||||
use tungstenite::protocol::WebSocket;
|
use tungstenite::protocol::WebSocket;
|
||||||
use tungstenite::util::NonBlockingResult;
|
use tungstenite::util::NonBlockingResult;
|
||||||
use tungstenite::{accept_hdr};
|
use tungstenite::protocol::Message;
|
||||||
|
use tokio_tungstenite::accept_hdr_async;
|
||||||
|
|
||||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||||
|
|
||||||
use serde_cbor::{to_vec};
|
use serde_cbor::{to_vec};
|
||||||
|
|
||||||
use failure::Error;
|
use std::io::{Error, ErrorKind};
|
||||||
use failure::{err_msg, format_err};
|
|
||||||
|
|
||||||
use net::TOKEN_HEADER;
|
use net::TOKEN_HEADER;
|
||||||
use rpc;
|
use rpc;
|
||||||
@ -29,182 +30,84 @@ use mtx;
|
|||||||
use pg::PgPool;
|
use pg::PgPool;
|
||||||
use account;
|
use account;
|
||||||
use account::Account;
|
use account::Account;
|
||||||
use events::{Message, Events};
|
use events::{Message as WsMessage, Events};
|
||||||
|
|
||||||
pub fn ws(mut client: WebSocket<TcpStream>, pool: PgPool, account: Option<Account>, events: Sender<Message>) {
|
// pub fn ws(mut client: WebSocket<Stream>, pool: PgPool, account: Option<Account>, events: Sender<Message>) {
|
||||||
let (tx, rx) = unbounded();
|
// let (tx, rx) = unbounded();
|
||||||
events.try_send(Message::Connect(tx)).unwrap();
|
// events.try_send(Message::Connect(tx)).unwrap();
|
||||||
|
|
||||||
loop {
|
// loop {
|
||||||
match client.read_message().no_block() {
|
// match client.read_message().no_block() {
|
||||||
Ok(msg) => {
|
// Ok(msg) => {
|
||||||
if let Some(msg) = msg {
|
// if let Some(msg) = msg {
|
||||||
match msg {
|
// match msg {
|
||||||
Binary(data) => {
|
// Binary(data) => {
|
||||||
let begin = Instant::now();
|
// let begin = Instant::now();
|
||||||
let db_connection = pool.get()
|
// let db_connection = pool.get()
|
||||||
.expect("unable to get db connection");
|
// .expect("unable to get db connection");
|
||||||
|
|
||||||
match rpc::receive(data, &db_connection, begin, &account) {
|
// match rpc::receive(data, &db_connection, begin, &account) {
|
||||||
Ok(reply) => {
|
// Ok(reply) => {
|
||||||
let response = to_vec(&reply)
|
// let response = to_vec(&reply)
|
||||||
.expect("failed to serialize response");
|
// .expect("failed to serialize response");
|
||||||
|
|
||||||
if let Err(e) = client.write_message(Binary(response)) {
|
// if let Err(e) = client.write_message(Binary(response)) {
|
||||||
// connection closed
|
// // connection closed
|
||||||
warn!("{:?}", e);
|
// warn!("{:?}", e);
|
||||||
return;
|
// return;
|
||||||
};
|
// };
|
||||||
|
|
||||||
// subscriptions.update(&reply).unwrap();
|
// // subscriptions.update(&reply).unwrap();
|
||||||
},
|
// },
|
||||||
Err(e) => {
|
// Err(e) => {
|
||||||
warn!("{:?}", e);
|
// warn!("{:?}", e);
|
||||||
let response = to_vec(&RpcError { err: e.to_string() })
|
// let response = to_vec(&RpcError { err: e.to_string() })
|
||||||
.expect("failed to serialize error response");
|
// .expect("failed to serialize error response");
|
||||||
|
|
||||||
if let Err(e) = client.write_message(Binary(response)) {
|
// if let Err(e) = client.write_message(Binary(response)) {
|
||||||
// connection closed
|
// // connection closed
|
||||||
warn!("{:?}", e);
|
// warn!("{:?}", e);
|
||||||
return;
|
// return;
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
_ => (),
|
// _ => (),
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
// match receiver.try_recv() {
|
// // match receiver.try_recv() {
|
||||||
// Ok(n) => handle_message(&subs, n, &mut websocket),
|
// // Ok(n) => handle_message(&subs, n, &mut websocket),
|
||||||
// Err(_) => (),
|
// // Err(_) => (),
|
||||||
// };
|
// // };
|
||||||
|
|
||||||
},
|
// },
|
||||||
// connection is closed
|
// // connection is closed
|
||||||
Err(e) => {
|
// Err(e) => {
|
||||||
warn!("{:?}", e);
|
// warn!("{:?}", e);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug,Clone,Serialize)]
|
#[derive(Debug,Clone,Serialize)]
|
||||||
struct RpcError {
|
struct RpcError {
|
||||||
err: String,
|
err: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[derive(Debug)]
|
pub fn start(pool: PgPool, events: Events) -> impl Future<Item = (), Error = Error> {
|
||||||
// struct Subscriptions {
|
let addr = "127.0.0.1:40055".parse().unwrap();
|
||||||
// account: Option<Uuid>,
|
let ws_server = TcpListener::bind(&addr).unwrap();
|
||||||
// game: Option<Uuid>,
|
|
||||||
// instance: Option<Uuid>,
|
|
||||||
// // account_instances: Vec<Uuid>,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl Subscriptions {
|
let wsf = ws_server.incoming().for_each(move |stream| {
|
||||||
// fn new(ws_pool: &PgPool, account: &Option<Account>, ws: &mut Ws) -> Result<Subscriptions, Error> {
|
|
||||||
// if let Some(a) = account {
|
|
||||||
// let db = ws_pool.get()?;
|
|
||||||
// let mut tx = db.transaction()?;
|
|
||||||
|
|
||||||
// // send account constructs
|
|
||||||
// let account_constructs = account::account_constructs(&mut tx, a)?;
|
|
||||||
// ws.client.write_message(Binary(to_vec(&rpc::RpcMessage::AccountConstructs(account_constructs))?))?;
|
|
||||||
|
|
||||||
// // get account instances
|
|
||||||
// // and send them to the client
|
|
||||||
// let account_instances = account::account_instances(&mut tx, a)?;
|
|
||||||
// // let instances = account_instances.iter().map(|i| i.id).collect::<Vec<Uuid>>();
|
|
||||||
// ws.client.write_message(Binary(to_vec(&rpc::RpcMessage::AccountInstances(account_instances))?))?;
|
|
||||||
|
|
||||||
// // get players
|
|
||||||
// // add to games
|
|
||||||
// tx.commit()?;
|
|
||||||
|
|
||||||
// return Ok(Subscriptions {
|
|
||||||
// account: Some(a.id),
|
|
||||||
// game: None,
|
|
||||||
// instance: None,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Ok(Subscriptions {
|
|
||||||
// account: None,
|
|
||||||
// game: None,
|
|
||||||
// instance: None
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn update(&mut self, msg: &RpcMessage) -> Result<&mut Subscriptions, Error> {
|
|
||||||
// match msg {
|
|
||||||
// RpcMessage::AccountState(a) => self.account = Some(a.id),
|
|
||||||
// RpcMessage::InstanceState(i) => self.instance = Some(i.id),
|
|
||||||
// RpcMessage::GameState(g) => self.game = Some(g.id),
|
|
||||||
// _ => (),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // info!("subscriptions updated {:?}", self);
|
|
||||||
|
|
||||||
// Ok(self)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// fn handle_message(subs: &Subscriptions, m: Message, ws: &mut Ws) {
|
|
||||||
// if let Some(msg) = match m {
|
|
||||||
// Message::Account(a) => {
|
|
||||||
// match subs.account {
|
|
||||||
// Some(wsa) => match wsa == a.id {
|
|
||||||
// true => Some(rpc::RpcMessage::AccountState(a)),
|
|
||||||
// false => None,
|
|
||||||
// },
|
|
||||||
// None => None,
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// Message::Instance(i) => {
|
|
||||||
// match subs.instance {
|
|
||||||
// Some(ci) => match ci == i.id {
|
|
||||||
// true => Some(rpc::RpcMessage::InstanceState(i)),
|
|
||||||
// false => None,
|
|
||||||
// },
|
|
||||||
// None => None,
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// Message::Game(g) => {
|
|
||||||
// match subs.game {
|
|
||||||
// Some(cg) => match cg == g.id {
|
|
||||||
// true => Some(rpc::RpcMessage::GameState(g)),
|
|
||||||
// false => None,
|
|
||||||
// },
|
|
||||||
// None => None,
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// Message::Connect(tx) => {
|
|
||||||
// info!("client connected {:?}", tx);
|
|
||||||
// None
|
|
||||||
// },
|
|
||||||
// // _ => None,
|
|
||||||
// } {
|
|
||||||
// ws.client.write_message(Binary(to_vec(&msg).unwrap())).unwrap();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn start(pool: PgPool, events: Events) {
|
|
||||||
let ws_server = TcpListener::bind("127.0.0.1:40055").unwrap();
|
|
||||||
for stream in ws_server.incoming() {
|
|
||||||
let ws_pool = pool.clone();
|
let ws_pool = pool.clone();
|
||||||
let events_tx = events.tx.clone();
|
let events_tx = events.tx.clone();
|
||||||
|
|
||||||
spawn(move || {
|
|
||||||
let (acc_s, acc_r) = unbounded();
|
let (acc_s, acc_r) = unbounded();
|
||||||
|
|
||||||
let nb_stream = stream.unwrap();
|
|
||||||
nb_stream.set_nonblocking(true).unwrap();
|
|
||||||
|
|
||||||
// search through the ws request for the auth cookie
|
// search through the ws request for the auth cookie
|
||||||
let cb = |req: &Request| {
|
let cb = move |req: &Request| {
|
||||||
let err = || ErrorResponse {
|
let err = || ErrorResponse {
|
||||||
error_code: StatusCode::FORBIDDEN,
|
error_code: StatusCode::FORBIDDEN,
|
||||||
headers: None,
|
headers: None,
|
||||||
@ -227,7 +130,10 @@ pub fn start(pool: PgPool, events: Events) {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut client = accept_hdr(nb_stream, cb).unwrap();
|
accept_hdr_async(stream, cb).and_then(move |ws_stream| {
|
||||||
|
info!("new connection");
|
||||||
|
|
||||||
|
let (sink, stream) = ws_stream.split();
|
||||||
|
|
||||||
// get a copy of the account
|
// get a copy of the account
|
||||||
let account = match acc_r.recv().unwrap() {
|
let account = match acc_r.recv().unwrap() {
|
||||||
@ -235,17 +141,16 @@ pub fn start(pool: PgPool, events: Events) {
|
|||||||
let db = ws_pool.get()
|
let db = ws_pool.get()
|
||||||
.expect("unable to get db connection");
|
.expect("unable to get db connection");
|
||||||
|
|
||||||
|
|
||||||
match account::from_token(&db, t) {
|
match account::from_token(&db, t) {
|
||||||
Ok(a) => {
|
Ok(a) => {
|
||||||
let state = to_vec(&rpc::RpcMessage::AccountState(a.clone())).unwrap();
|
let state = to_vec(&rpc::RpcMessage::AccountState(a.clone())).unwrap();
|
||||||
client.write_message(Binary(state)).unwrap();
|
// client.write_message(Binary(state)).unwrap();
|
||||||
|
|
||||||
let mut tx = db.transaction().unwrap();
|
let mut tx = db.transaction().unwrap();
|
||||||
let shop = mtx::account_shop(&mut tx, &a).unwrap();
|
let shop = mtx::account_shop(&mut tx, &a).unwrap();
|
||||||
let shop = to_vec(&rpc::RpcMessage::AccountShop(shop)).unwrap();
|
let shop = to_vec(&rpc::RpcMessage::AccountShop(shop)).unwrap();
|
||||||
|
|
||||||
client.write_message(Binary(shop)).unwrap();
|
// client.write_message(Binary(shop)).unwrap();
|
||||||
|
|
||||||
// tx doesn't change anything
|
// tx doesn't change anything
|
||||||
tx.commit().unwrap();
|
tx.commit().unwrap();
|
||||||
@ -254,14 +159,34 @@ pub fn start(pool: PgPool, events: Events) {
|
|||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("{:?}", e);
|
warn!("{:?}", e);
|
||||||
return;
|
None
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
ws(client, ws_pool, account, events_tx)
|
let ws_reader = stream.for_each(move |message: Message| {
|
||||||
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
|
tokio::spawn(ws_reader.then(move |_| {
|
||||||
|
println!("Connection closed.");
|
||||||
|
Ok(())
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
info!("{:?}", account);
|
||||||
|
Ok(())
|
||||||
|
// ws(client, ws_pool, account, events_tx)
|
||||||
|
|
||||||
|
})
|
||||||
|
.map_err(|e| {
|
||||||
|
warn!("Error during the websocket handshake occurred: {}", e);
|
||||||
|
Error::new(ErrorKind::Other, e)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
return wsf;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user