diff --git a/Cargo.lock b/Cargo.lock index cb28267..e454473 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,7 +111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.3.4", "bitflags 1.3.2", "bytes", "futures-util", @@ -119,7 +119,7 @@ dependencies = [ "http-body 0.4.6", "hyper 0.14.32", "itoa", - "matchit", + "matchit 0.7.3", "memchr", "mime", "percent-encoding", @@ -132,6 +132,40 @@ dependencies = [ "tower-service", ] +[[package]] +name = "axum" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8" +dependencies = [ + "axum-core 0.5.0", + "bytes", + "form_urlencoded", + "futures-util", + "http 1.2.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.6.0", + "hyper-util", + "itoa", + "matchit 0.8.4", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper 1.0.2", + "tokio", + "tower 0.5.2", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "axum-core" version = "0.3.4" @@ -149,6 +183,26 @@ dependencies = [ "tower-service", ] +[[package]] +name = "axum-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733" +dependencies = [ + "bytes", + "futures-util", + "http 1.2.0", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.2", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "backtrace" version = "0.3.74" @@ -422,6 +476,7 @@ name = "durak-frthistime" version = "0.1.0" dependencies = [ "anyhow", + "axum 0.8.1", "clap", "console-subscriber", "crossterm", @@ -435,6 +490,7 @@ dependencies = [ "serde_json", "sha256", "tokio", + "tower 0.5.2", "tracing", "tracing-subscriber", ] @@ -1137,6 +1193,12 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + [[package]] name = "memchr" version = "2.7.4" @@ -1739,6 +1801,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +dependencies = [ + "itoa", + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2057,7 +2129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" dependencies = [ "async-trait", - "axum", + "axum 0.6.20", "base64 0.21.7", "bytes", "futures-core", @@ -2111,6 +2183,7 @@ dependencies = [ "tokio", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -2131,6 +2204,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", diff --git a/Cargo.toml b/Cargo.toml index 117a69a..e3674ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ name = "client" path = "src/bin/client.rs" [dependencies] +axum = "0.8.1" +tower = "0.5.2" reqwest = "0.12.0" hyper = { version = "1", features = ["full"] } http-body-util = "0.1" diff --git a/src/bin/client.rs b/src/bin/client.rs index 758175c..54c96c3 100644 --- a/src/bin/client.rs +++ b/src/bin/client.rs @@ -1,4 +1,4 @@ -use lib::{client::Client, message::{Message, MessageKind}, message_read::MessageReader}; +use lib::{client::Client, message::{Message, MessageKind}, message_read::MessageReader, player::Player}; use crossterm::{ execute, terminal::{ @@ -27,8 +27,17 @@ pub async fn main() -> anyhow::Result<()> { // Clear(ClearType::All), // )?; - let body = reqwest::get("http://127.0.0.1:8080").await?.text().await?; - println!("body = {body:?}"); + let addr = "http://127.0.0.1:8080"; + + let client = reqwest::Client::new(); + + let response = client + .post([&addr, "/create/player"].concat()) + .body(Player::new()?.encode()?) + .send().await? + .text().await?; + + println!("{}", response); Ok(()) } diff --git a/src/db.rs b/src/db.rs new file mode 100644 index 0000000..ca4965b --- /dev/null +++ b/src/db.rs @@ -0,0 +1,23 @@ +use std::sync::{Arc, Mutex}; +use std::collections::HashMap; +use axum::body::Bytes; + +pub type Db = Arc>>; + +#[derive(Clone)] +pub struct AppState { + pub lobbies: Db, + pub players: Db, +} + +impl AppState { + pub fn new() -> Self { + let lobbies = Arc::new(Mutex::new(HashMap::new())); + let players = Arc::new(Mutex::new(HashMap::new())); + + Self { + lobbies, + players, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 5493869..3efbd9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,3 +8,5 @@ pub mod message; pub mod message_read; pub mod constant; pub mod routine; +pub mod db; +pub mod router; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index d4e82b7..0000000 --- a/src/main.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::collections::HashMap; -use std::io::{self, Error}; -use std::net::SocketAddr; - -use lib::lobby::Lobby; -use lib::player::Player; -use std::sync::{Arc, Mutex}; - -use anyhow::Result; -use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}; -use tokio::net::{TcpListener, TcpStream}; - -async fn handle_connection(mut stream: TcpStream, addr: SocketAddr) -> (Option, Option) { - let (mut read, mut write) = stream.split(); - - let mut buf = [0; 1024]; - - let mut name = String::new(); - write.write_all(b"provide name\n").await.expect("failed to write to socket"); - - let n = match read.read(&mut buf).await { - Ok(0) => return (None, None), - Ok(n) => n, - Err(e) => { - eprintln!("failed to read from socket; err: {:?}", e); - return (None, None); - }, - }; - - name = String::from_utf8_lossy(&buf[0..n]).to_string(); - -// if let Err(e) = write.write_all(&buf[0..n]).await { -// eprintln!("failed to write to socket; err = {:?}", e); -// return (None, None); -// } - - let player = Player::new(addr, &name); - - write.write_all(b"your name is\n").await.expect("failed to write to socket"); - write.write_all(name.as_bytes()).await.expect("failed to write to socket"); - - (Some(player), None) -} - -#[tokio::main] -async fn main() -> io::Result<()> { - let address = "127.0.0.1:8080".to_string(); - let listener = TcpListener::bind(&address).await?; - - let mut lobbies: Arc>> = Arc::new(Mutex::new(HashMap::new())); - - loop { - let (mut stream, addr) = listener.accept().await?; - - println!("new connection from: {}", addr); - - let lobby_player_handle = tokio::spawn(handle_connection(stream, addr)); - - let (player, lobby) = lobby_player_handle.await?; - - match lobby { - Some(lobby) => lobbies.insert(lobby.get_id(), lobby), - None => continue, - }; - - } - - Ok(()) -} diff --git a/src/message.rs b/src/message.rs index a3f3981..6dadb34 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,10 +1,11 @@ +use std::fmt::Display; +use axum::body::to_bytes; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { pub from: String, pub message_kind: MessageKind, - pub length: u16, pub content: String, } @@ -20,12 +21,10 @@ impl Message { pub fn new(from: &str, message_kind: MessageKind, content: impl Into) -> anyhow::Result { let from = from.into(); let content = content.into(); - let length = content.len() as u16; Ok(Self { from, message_kind, - length, content, }) } @@ -42,3 +41,9 @@ impl Message { Ok(message) } } + +impl Display for Message { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + todo!() + } +} diff --git a/src/player.rs b/src/player.rs index 095f521..208b88b 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,41 +1,42 @@ -use tokio::{io::AsyncReadExt, net::TcpStream}; -use std::net::SocketAddr; +use petname::Generator; use serde::{Deserialize, Serialize}; use sha256::digest; -use crate::{card::Card, message_read::MessageReader}; +use crate::card::Card; #[derive(Serialize, Deserialize, Eq, PartialEq, Hash, Clone)] pub struct Player { - // addr will change because at this stage i really - // don't know what i am doing - // it will probably be something like id or playerid - // or some other identifier idk - pub addr: SocketAddr, - // same goes for id because rn it's just the sha256 of - // the ip pub id: String, pub name: String, pub hand: Vec, } impl Player { - pub async fn new(addr: SocketAddr, name: &str) -> anyhow::Result> { + pub fn new() -> anyhow::Result { let hand_empty: Vec = Vec::new(); - let to_digest: String = addr.to_string(); + + let name = petname::Petnames::default().generate_one(2, "-").expect("no nomi"); + let to_digest = &name; let id = digest(to_digest); - Ok(Some(Player { - addr, + Ok(Player { id, - name: name.to_string(), + name, hand: hand_empty, - })) + }) } - pub fn get_addr(self) -> SocketAddr { - self.addr + pub fn encode(&self) -> anyhow::Result { + let player_json: String = serde_json::to_string(self)?; + + Ok(player_json) + } + + pub fn decode(player: String) -> anyhow::Result { + let player: Player = serde_json::from_str(&player)?; + + Ok(player) } pub fn get_name(self) -> String { diff --git a/src/router.rs b/src/router.rs new file mode 100644 index 0000000..dc58a3a --- /dev/null +++ b/src/router.rs @@ -0,0 +1,46 @@ +use axum::{ + Router, + body::Bytes, + extract::{ + State, + Json, + rejection::JsonRejection, + }, +}; + +use crate::message::Message; +use crate::db::AppState; + +pub struct App { + pub db: AppState, + pub router: Router, +} + +impl App { + pub fn new() -> Self { + let db = AppState::new(); + let router: Router = Router::new(); + + Self { + db, + router, + } + } + + pub async fn echo(body: Bytes) -> Bytes { + body + } + + pub async fn create_player( + State(db): State, + json_body: Result, JsonRejection>, + ) + { + match json_body { + Ok(Json(message)) => { + println!("{:?}", message); + } + Err(e) => eprintln!("{e}"), + } + } +} diff --git a/src/server.rs b/src/server.rs index 1075248..82f2e8f 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,13 +1,7 @@ -use tokio::{io::{AsyncReadExt, AsyncWriteExt, BufReader}, net::{tcp::WriteHalf, TcpListener}}; -use std::net::SocketAddr; -use crate::{message::{Message, MessageKind}, message_read::MessageReader, server}; -use std::convert::Infallible; -use http_body_util::Full; -use hyper::body::Bytes; -use hyper::server::conn::http1; -use hyper::service::service_fn; -use hyper::{Request, Response}; -use hyper_util::rt::TokioIo; +use tokio::net::TcpListener; +use crate::router::App; + +use axum::routing::{get, post}; pub struct Server { pub host: String, @@ -22,35 +16,23 @@ impl Server { } } - pub async fn handle_request(_: Request) -> Result>, Infallible> { - Ok(Response::new(Full::new(Bytes::from("Hello, toto")))) - } - #[allow(unreachable_code)] pub async fn run(&mut self) -> anyhow::Result<()> { let listener = TcpListener::bind(format!( "{}:{}", self.host, self.port )).await?; - println!("Server is running on {}:{}", self.host, self.port); - loop { - let (mut stream, addr) = listener.accept().await?; - println!("Connection received from {}", addr); + let app = App::new(); - let io = TokioIo::new(stream); + let router = app.router + .route("/echo", post(App::echo)) + .route("/create/player", post(App::create_player)) + .with_state(app.db); - tokio::task::spawn(async move { - if let Err(e) = http1::Builder::new() - .serve_connection(io, service_fn(Self::handle_request)) - .await - { - eprintln!("error serving connection: {:?}", e); - } - }); - } + axum::serve(listener, router).await.unwrap(); Ok(()) }