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

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(()))
}
}