You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
4.1 KiB
124 lines
4.1 KiB
use tonic::{Request, Response, Status};
|
|
|
|
use log::info;
|
|
|
|
use tokio::sync::{mpsc, RwLock};
|
|
|
|
use std::{collections::HashMap, sync::Arc};
|
|
|
|
use super::grpc::common::Name;
|
|
use super::grpc::connection_service::connection_server::Connection;
|
|
use super::grpc::connection_service::{Game, LobbyCode, LobbyConfig, UserId};
|
|
|
|
pub use super::grpc::connection_service::connection_server::ConnectionServer;
|
|
|
|
use super::votes;
|
|
|
|
use super::client_id;
|
|
|
|
use crate::{db, games::RunningGame};
|
|
|
|
pub struct ConnectionService {
|
|
pub conn: RwLock<db::DbClient>,
|
|
pub properties: Arc<crate::server_properties::ServerProperties>,
|
|
pub games: Arc<Vec<crate::games::Game>>,
|
|
pub running_games: Arc<RwLock<HashMap<u32, RwLock<(u32, RunningGame, super::votes::Modifiable<Option<super::grpc::game::MessageStatus>>)>>>>,
|
|
pub voting: votes::VotingSystem,
|
|
}
|
|
|
|
#[tonic::async_trait]
|
|
impl Connection for ConnectionService {
|
|
async fn connect(&self, request: Request<Name>) -> Result<Response<UserId>, Status> {
|
|
let name = request.into_inner().name;
|
|
// let mut conn = self.conn.acquire().await;
|
|
let uuid = self.conn.write().await.add_user(name.clone()).await?;
|
|
info!("Connected {}[{}]", name, uuid);
|
|
Ok(Response::new(UserId {
|
|
id: uuid.to_hyphenated().to_string(),
|
|
}))
|
|
}
|
|
|
|
async fn join_lobby_with_code(
|
|
&self,
|
|
request: Request<LobbyCode>,
|
|
) -> Result<Response<()>, Status> {
|
|
let uuid = client_id::get(request.metadata()).map_err(|x| match x {
|
|
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"),
|
|
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"),
|
|
})?;
|
|
let lobby = request.get_ref().code;
|
|
if self.running_games.read().await.contains_key(&lobby) {
|
|
return Err(Status::permission_denied(
|
|
"Can't join a lobby where a game is running",
|
|
));
|
|
}
|
|
let mut conn = self.conn.write().await;
|
|
conn.join_lobby(uuid, lobby).await;
|
|
self.voting.updated_users(&lobby).await;
|
|
Ok(Response::new(()))
|
|
}
|
|
|
|
async fn create_lobby(
|
|
&self,
|
|
request: Request<LobbyConfig>,
|
|
) -> Result<Response<LobbyCode>, Status> {
|
|
let uuid = client_id::get(request.metadata()).map_err(|x| match x {
|
|
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"),
|
|
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"),
|
|
})?;
|
|
let mut conn = self.conn.write().await;
|
|
let lobby = conn.create_lobby(request.into_inner().public).await;
|
|
conn.join_lobby(uuid, lobby).await;
|
|
self.voting.updated_users(&lobby).await;
|
|
Ok(Response::new(LobbyCode { code: lobby }))
|
|
}
|
|
|
|
async fn name(&self, _request: Request<()>) -> Result<Response<Name>, Status> {
|
|
Ok(Response::new(Name {
|
|
name: self.properties.name.clone(),
|
|
}))
|
|
}
|
|
|
|
type getGamesStream = mpsc::UnboundedReceiver<Result<Game, tonic::Status>>;
|
|
|
|
async fn get_games(&self, _: Request<()>) -> Result<Response<Self::getGamesStream>, Status> {
|
|
let (sender, receiver) = mpsc::unbounded_channel();
|
|
for (id, game) in self.games.iter().enumerate() {
|
|
sender
|
|
.send(Ok(Game {
|
|
id: id as u32,
|
|
name: game.name.clone(),
|
|
version: game.version.clone(),
|
|
authors: game.authors.clone(),
|
|
}))
|
|
.unwrap();
|
|
}
|
|
Ok(Response::new(receiver))
|
|
}
|
|
|
|
type getPublicLobbiesStream = mpsc::UnboundedReceiver<Result<LobbyCode, tonic::Status>>;
|
|
|
|
async fn get_public_lobbies(
|
|
&self,
|
|
_request: Request<()>,
|
|
) -> Result<Response<Self::getPublicLobbiesStream>, Status> {
|
|
let (sender, receiver) = mpsc::unbounded_channel();
|
|
let mut conn = self.conn.write().await;
|
|
for id in conn.get_public_lobbies().await {
|
|
sender.send(Ok(LobbyCode { code: id })).unwrap();
|
|
}
|
|
Ok(Response::new(receiver))
|
|
}
|
|
|
|
async fn disconnect(&self, request: Request<()>) -> Result<Response<()>, Status> {
|
|
let uuid = client_id::get(request.metadata()).map_err(|x| match x {
|
|
client_id::Error::NotSet => Status::failed_precondition("client_id must be set"),
|
|
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"),
|
|
})?;
|
|
let mut conn = self.conn.write().await;
|
|
// log::warn!("Trying to disconnect");
|
|
conn.disconnect(uuid).await;
|
|
// log::warn!("Disconnected");
|
|
Ok(Response::new(()))
|
|
}
|
|
}
|
|
|