}
#[get("/<token>")]
-fn loading(token : InstanceAccess) -> Result<Template,RE> {
+fn loading(token : InstanceAccess<PlayerId>) -> Result<Template,RE> {
let c = LoadingRenderContext { token : token.raw_token };
Ok(Template::render("loading",&c))
}
fn session(form : Json<SessionForm>) -> Result<Template,RE> {
// make session in this game, log a message to other players
let iad = lookup_token(&form.token).ok_or_else(|| anyhow!("unknown token"))?;
+ let player = iad.ident;
let c = {
- let mut ig = iad.i.lock().map_err(|e| anyhow!("lock poison {:?}",&e))?;
- let _player = ig.gs.players.get_mut(iad.player)
+ let mut ig = iad.g.lock().map_err(|e| anyhow!("lock poison {:?}",&e))?;
+ let pl = ig.gs.players.get_mut(player)
.ok_or_else(|| anyhow!("player deleted"))?;
- let client = Client { };
- let clientid = ig.clients[iad.player].insert(client);
+ let client = Client { player };
+ let clientid = ig.clients.insert(client);
let mut uses = vec![];
let mut defs = vec![];
SessionRenderContext {
clientid,
- player : iad.player,
+ player,
defs,
uses,
}
#[derive(Debug,Serialize,Deserialize)]
struct ApiGrab {
t : String,
- c : ClientId,
p : VisiblePieceId,
g : Counter,
s : ClientSequence,
#[throws(RE)]
fn api_grab(form : Json<ApiGrab>) -> impl response::Responder<'static> {
let iad = lookup_token(&form.t).ok_or_else(||anyhow!("unknown token"))?;
- let mut g = iad.i.lock().map_err(|e| anyhow!("lock poison {:?}",&e))?;
+ let client = iad.ident;
+ let mut g = iad.g.lock().map_err(|e| anyhow!("lock poison {:?}",&e))?;
let g = &mut *g;
- let client = form.c;
+ let cl = &g.clients.get(client).ok_or_else(||anyhow!("unknown client"))?;
+ // ^ can only fail if we raced
+ let player = cl.player;
let r : Result<(),OpError> = (||{
let piece = decode_visible_pieceid(form.p);
let gs = &mut g.gs;
else { p.gen_before_lastclient };
if u_gen > form.g { Err(OpError::Conflict)? }
if p.held != None { Err(OpError::PieceHeld)? };
- p.held = Some(iad.player);
+ p.held = Some(player);
gs.gen += 1;
let gen = gs.gen;
if client != p.lastclient {
u : UpdatePayload::PieceUpdate(piece, p.mk_update()),
};
p.gen_lastclient = gen;
- for (tplayer, tpl) in &g.gs.players {
- for (tclient, tcl) in &mut g.clients[tplayer] {
- if tclient == client {
- tcl.transmit_update(&Update {
- gen,
- u : UpdatePayload::ClientSequence(form.s),
- });
- } else {
- tcl.transmit_update(&update);
- }
- }
+ for (tclient, tcl) in &mut g.clients {
+ if tclient == client {
+ tcl.transmit_update(&Update {
+ gen,
+ u : UpdatePayload::ClientSequence(form.s),
+ });
+ } else {
+ tcl.transmit_update(&update);
+ }
}
Ok(())
})();
}
*/
-#[get("/_/updates/<token>/<clientid>")]
+#[get("/_/updates/<token>")]
#[throws(RE)]
-fn updates(token : &RawStr, clientid : String) -> impl response::Responder<'static> {
- let iad = lookup_token(token.as_str()).ok_or_else(|| anyhow!("unknown token"))?;
- let clientid = TryFrom::try_from(clientid.as_ref())?;
+fn updates(token : InstanceAccess<ClientId>)
+ -> impl response::Responder<'static> {
+ let iad = token.i;
+ let client = iad.ident;
let _ = {
- let mut ig = iad.i.lock().map_err(|e| anyhow!("lock poison {:?}",&e))?;
+ let mut ig = iad.g.lock().map_err(|e| anyhow!("lock poison {:?}",&e))?;
let g = &mut ig.gs;
- let _player = g.players.get_mut(iad.player)
- .ok_or_else(|| anyhow!("user deleted"))?;
- let _client = ig.clients[iad.player].get_mut(clientid)
- .ok_or_else(|| anyhow!("client deleted"))?;
+ let cl = ig.clients.get(client).ok_or_else(|| anyhow!("no client"))?;
+ let player = cl.player;
};
let tc = TestCounterInner { next : 0 };
let tc = BufReader::new(tc);
visible_slotmap_key!{ PlayerId('#') }
#[derive(Clone,Debug,Eq,PartialEq,Ord,PartialOrd,Hash)]
-struct RawToken (String);
+pub struct RawToken (String);
impl Borrow<str> for RawToken {
fn borrow(&self) -> &str { &self.0 }
}
pub struct Client {
+ pub player : PlayerId,
}
impl Client {
}
pub struct Instance {
- /* game state goes here */
pub gs : GameState,
- pub clients : SecondarySlotMap<PlayerId,DenseSlotMap<ClientId,Client>>,
+ pub clients : DenseSlotMap<ClientId,Client>,
}
#[derive(Clone)]
-pub struct InstanceAccessDetails {
- pub i : Arc<Mutex<Instance>>,
- pub player : PlayerId,
+pub struct InstanceAccessDetails<Id> {
+ pub g : Arc<Mutex<Instance>>,
+ pub ident : Id,
}
#[derive(Clone)]
-pub struct InstanceAccess<'i> {
+pub struct InstanceAccess<'i, Id> {
pub raw_token : &'i str,
- pub i : InstanceAccessDetails,
+ pub i : InstanceAccessDetails<Id>,
}
+pub type TokenTable<Id> = HashMap<RawToken, InstanceAccessDetails<Id>>;
+
#[derive(Default)]
struct Global {
// lock hierarchy: this is the innermost lock
- tokens : RwLock<HashMap<RawToken, InstanceAccessDetails>>,
+ players : RwLock<TokenTable<PlayerId>>,
+ clients : RwLock<TokenTable<ClientId>>,
// xxx delete instances at some point!
}
static ref GLOBAL : Global = Default::default();
}
-pub fn lookup_token(s : &str) -> Option<InstanceAccessDetails> {
- GLOBAL.tokens.read().unwrap().get(s).cloned()
+pub trait AccessId : Copy + Clone + 'static {
+ fn global_tokens() -> &'static RwLock<TokenTable<Self>>;
+}
+
+impl AccessId for PlayerId {
+ fn global_tokens() -> &'static RwLock<TokenTable<Self>> { &GLOBAL.players }
+}
+impl AccessId for ClientId {
+ fn global_tokens() -> &'static RwLock<TokenTable<Self>> { &GLOBAL.clients }
+}
+
+pub fn lookup_token<Id : AccessId>(s : &str)
+ -> Option<InstanceAccessDetails<Id>> {
+ Id::global_tokens().read().unwrap().get(s).cloned()
}
const XXX_PLAYERS_TOKENS : &[(&str, &str)] = &[
("ccg9kzoTh758QrVE1xMY7BQWB36dNJTx", "bob"),
];
-impl<'r> FromParam<'r> for InstanceAccess<'r> {
+impl<'r, Id> FromParam<'r> for InstanceAccess<'r, Id>
+ where Id : AccessId
+{
type Error = E;
#[throws(E)]
fn from_param(param: &'r RawStr) -> Self {
- let g = GLOBAL.tokens.read().unwrap();
+ let g = Id::global_tokens().read().unwrap();
let token = param.as_str();
let i = g.get(token).ok_or_else(|| anyhow!("unknown token"))?;
InstanceAccess { raw_token : token, i : i.clone() }
}
pub fn xxx_global_setup() {
- let i = Instance {
+ let gi = Instance {
gs : xxx_gamestate_init(),
clients : Default::default(),
};
- let i = Arc::new(Mutex::new(i));
- let mut ig = i.lock().unwrap();
+ let g = Arc::new(Mutex::new(gi));
+ let mut ig = g.lock().unwrap();
for (token, nick) in XXX_PLAYERS_TOKENS {
- let nu = Player {
+ let np = Player {
nick : nick.to_string(),
};
- let player = ig.gs.players.insert(nu);
- ig.clients.insert(player, Default::default());
- let ia = InstanceAccessDetails { i : i.clone(), player };
- GLOBAL.tokens.write().unwrap().insert(
+ let player = ig.gs.players.insert(np);
+ let ia = InstanceAccessDetails { g : g.clone(), ident : player };
+ GLOBAL.players.write().unwrap().insert(
RawToken(token.to_string()), ia
);
}