aboutsummaryrefslogtreecommitdiff
path: root/planetwars-server
diff options
context:
space:
mode:
Diffstat (limited to 'planetwars-server')
-rw-r--r--planetwars-server/src/modules/bot_api.rs71
1 files changed, 45 insertions, 26 deletions
diff --git a/planetwars-server/src/modules/bot_api.rs b/planetwars-server/src/modules/bot_api.rs
index 0f1ff82..2face62 100644
--- a/planetwars-server/src/modules/bot_api.rs
+++ b/planetwars-server/src/modules/bot_api.rs
@@ -2,8 +2,8 @@ pub mod pb {
tonic::include_proto!("grpc.planetwars.bot_api");
}
+use std::collections::HashMap;
use std::net::SocketAddr;
-use std::ops::DerefMut;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
@@ -23,7 +23,35 @@ use crate::{ConnectionPool, MAPS_DIR, MATCHES_DIR};
use super::matches::code_bundle_to_botspec;
pub struct BotApiServer {
- sync_thing: ServerSyncThing,
+ router: PlayerRouter,
+}
+
+/// Routes players to their handler
+#[derive(Clone)]
+struct PlayerRouter {
+ routing_table: Arc<Mutex<HashMap<String, SyncThingData>>>,
+}
+
+impl PlayerRouter {
+ pub fn new() -> Self {
+ PlayerRouter {
+ routing_table: Arc::new(Mutex::new(HashMap::new())),
+ }
+ }
+}
+
+// TODO: implement a way to expire entries
+impl PlayerRouter {
+ fn put(&self, player_id: String, entry: SyncThingData) {
+ let mut routing_table = self.routing_table.lock().unwrap();
+ routing_table.insert(player_id, entry);
+ }
+
+ fn get(&self, player_id: &str) -> Option<SyncThingData> {
+ // TODO: this design does not allow for reconnects. Is this desired?
+ let mut routing_table = self.routing_table.lock().unwrap();
+ routing_table.remove(player_id)
+ }
}
#[tonic::async_trait]
@@ -36,7 +64,8 @@ impl pb::bot_api_service_server::BotApiService for BotApiServer {
) -> Result<Response<Self::ConnectBotStream>, Status> {
println!("bot connected");
let stream = req.into_inner();
- let sync_data = self.sync_thing.streams.lock().unwrap().take().unwrap();
+ // TODO: return error when player does not exist
+ let sync_data = self.router.get("test_player").unwrap();
sync_data.tx.send(stream).unwrap();
Ok(Response::new(UnboundedReceiverStream::new(
sync_data.server_messages,
@@ -44,26 +73,13 @@ impl pb::bot_api_service_server::BotApiService for BotApiServer {
}
}
-#[derive(Clone)]
-struct ServerSyncThing {
- streams: Arc<Mutex<Option<SyncThingData>>>,
-}
-
struct SyncThingData {
tx: oneshot::Sender<Streaming<pb::PlayerRequestResponse>>,
server_messages: mpsc::UnboundedReceiver<Result<pb::PlayerRequest, Status>>,
}
-impl ServerSyncThing {
- fn new() -> Self {
- ServerSyncThing {
- streams: Arc::new(Mutex::new(None)),
- }
- }
-}
-
struct RemoteBotSpec {
- sync_thing: ServerSyncThing,
+ router: PlayerRouter,
}
#[tonic::async_trait]
@@ -76,10 +92,13 @@ impl runner::BotSpec for RemoteBotSpec {
) -> Box<dyn PlayerHandle> {
let (tx, rx) = oneshot::channel();
let (server_msg_snd, server_msg_recv) = mpsc::unbounded_channel();
- *self.sync_thing.streams.lock().unwrap().deref_mut() = Some(SyncThingData {
- tx,
- server_messages: server_msg_recv,
- });
+ self.router.put(
+ "test_player".to_string(),
+ SyncThingData {
+ tx,
+ server_messages: server_msg_recv,
+ },
+ );
let client_messages = rx.await.unwrap();
tokio::spawn(handle_bot_messages(player_id, event_bus, client_messages));
@@ -119,7 +138,7 @@ impl PlayerHandle for RemoteBotHandle {
}
}
-async fn run_match(sync_thing: ServerSyncThing, pool: ConnectionPool) {
+async fn run_match(router: PlayerRouter, pool: ConnectionPool) {
let conn = pool.get().await.unwrap();
let opponent = db::bots::find_bot_by_name("simplebot", &conn).unwrap();
@@ -127,7 +146,7 @@ async fn run_match(sync_thing: ServerSyncThing, pool: ConnectionPool) {
let log_file_name = "remote_match.log";
- let remote_bot_spec = RemoteBotSpec { sync_thing };
+ let remote_bot_spec = RemoteBotSpec { router };
let match_config = runner::MatchConfig {
map_path: PathBuf::from(MAPS_DIR).join("hex.json"),
@@ -147,9 +166,9 @@ async fn run_match(sync_thing: ServerSyncThing, pool: ConnectionPool) {
}
pub async fn run_bot_api(pool: ConnectionPool) {
- let sync_thing = ServerSyncThing::new();
- tokio::spawn(run_match(sync_thing.clone(), pool));
- let server = BotApiServer { sync_thing };
+ let router = PlayerRouter::new();
+ tokio::spawn(run_match(router.clone(), pool));
+ let server = BotApiServer { router };
let addr = SocketAddr::from(([127, 0, 0, 1], 50051));
Server::builder()