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.
156 lines
4.9 KiB
156 lines
4.9 KiB
use tonic::{transport::Server, Request, Response, Status};
|
|
|
|
use log::info;
|
|
|
|
use std::sync::Arc;
|
|
|
|
mod game;
|
|
|
|
use game::connection_server::{Connection, ConnectionServer};
|
|
use game::lobby_server::{Lobby, LobbyServer};
|
|
use game::{LobbyCode, Null, UserId, Name, CardId, Image};
|
|
|
|
use crate::db;
|
|
|
|
pub struct ConnectionService {
|
|
conn: Arc<db::DbPool>,
|
|
properties: Arc<crate::server_properties::ServerProperties>
|
|
}
|
|
|
|
#[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 = conn.add_user(&name).await;
|
|
info!("Connected {}[{}]", name, uuid);
|
|
conn.close().await;
|
|
Ok(Response::new(UserId {
|
|
id: uuid.to_hyphenated().to_string(),
|
|
}))
|
|
}
|
|
|
|
async fn join_lobby_with_code(
|
|
&self,
|
|
request: Request<LobbyCode>,
|
|
) -> Result<Response<Null>, 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;
|
|
let mut conn = self.conn.acquire().await;
|
|
conn.join_lobby(uuid, lobby).await;
|
|
conn.close().await;
|
|
Ok(Response::new(Null{}))
|
|
}
|
|
|
|
async fn join_lobby_without_code(
|
|
&self,
|
|
request: Request<Null>,
|
|
) -> 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.acquire().await;
|
|
let lobby = conn.create_lobby().await;
|
|
conn.join_lobby(uuid, lobby).await;
|
|
conn.close().await;
|
|
Ok(Response::new(LobbyCode{code: lobby}))
|
|
}
|
|
|
|
async fn name(
|
|
&self,
|
|
_request: Request<Null>,
|
|
) -> Result<Response<game::Name>, Status> {
|
|
Ok(Response::new(game::Name {name: self.properties.name.clone() }))
|
|
}
|
|
}
|
|
|
|
|
|
use tokio::sync::mpsc;
|
|
|
|
pub struct LobbyService {
|
|
conn: Arc<db::DbPool>,
|
|
games: Arc<Vec<crate::games::Game>>,
|
|
}
|
|
|
|
#[tonic::async_trait]
|
|
impl Lobby for LobbyService {
|
|
type getGamesStream = mpsc::UnboundedReceiver<Result<game::Game, tonic::Status>>;
|
|
|
|
async fn get_games(
|
|
&self,
|
|
_: Request<Null>,
|
|
) -> Result<Response<Self::getGamesStream>, Status> {
|
|
let (sender, receiver) = mpsc::unbounded_channel();
|
|
for (id, game) in self.games.iter().enumerate() {
|
|
sender.send(Ok(game::Game {id: id as u64, name: game.name.clone(), version: game.version.clone(), authors: game.authors.clone()})).unwrap();
|
|
}
|
|
Ok(Response::new(receiver))
|
|
}
|
|
|
|
async fn get_card_image(&self, request: tonic::Request<CardId>) -> Result<tonic::Response<Image>, tonic::Status> {
|
|
let id = request.into_inner();
|
|
let game = &self.games.as_ref()[id.game_id as usize];
|
|
let card = game.get_card_path(&id.card_id);
|
|
let mut buffer = Vec::new();
|
|
image::open(&card).expect(&format!("Error loading the image in {:?}", card)).write_to(&mut buffer, image::ImageOutputFormat::Png).unwrap();
|
|
Ok(Response::new(Image {content: buffer}))
|
|
}
|
|
|
|
async fn vote(
|
|
&self,
|
|
request: Request<game::Vote>,
|
|
) -> Result<Response<Null>, Status> {
|
|
todo!()
|
|
}
|
|
|
|
async fn ready(
|
|
&self,
|
|
request: Request<Null>,
|
|
) -> Result<Response<Null>, Status> {
|
|
todo!()
|
|
}
|
|
|
|
async fn status(
|
|
&self,
|
|
request: Request<Null>,
|
|
) -> Result<Response<game::LobbyStatus>, Status> {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
pub async fn start(pool: db::DbPool, games: Vec<crate::games::Game>, properties: crate::server_properties::ServerProperties) {
|
|
let arc = Arc::new(pool);
|
|
let properties = Arc::new(properties);
|
|
let connection = ConnectionService { conn: arc.clone(), properties };
|
|
let lobby = LobbyService {conn: arc.clone(), games: Arc::new(games)};
|
|
|
|
Server::builder()
|
|
.add_service(ConnectionServer::new(connection))
|
|
.add_service(LobbyServer::new(lobby))
|
|
.serve("0.0.0.0:50052".parse().unwrap())
|
|
.await
|
|
.unwrap();
|
|
}
|
|
|
|
mod client_id {
|
|
pub fn get(
|
|
metadata: &tonic::metadata::MetadataMap,
|
|
) -> Result<uuid::Uuid, Error> {
|
|
metadata
|
|
.get("client_id")
|
|
.ok_or(Error::NotSet)
|
|
.and_then(|x| {
|
|
uuid::Uuid::parse_str(x.to_str().map_err(|_| Error::MalformedUuid)?)
|
|
.map_err(|_| Error::MalformedUuid)
|
|
})
|
|
}
|
|
|
|
pub enum Error {
|
|
MalformedUuid,
|
|
NotSet,
|
|
}
|
|
}
|
|
|