Compare commits

...

10 commits

Author SHA1 Message Date
clizia
f969a9fc21 added crossterm 2025-01-27 17:35:50 +01:00
clizia
d001bacae8 added contants and message kind 2025-01-26 17:19:15 +01:00
clizia
a085ae78bb upsi 2025-01-26 02:24:35 +01:00
clizia
ea80597050 bunch of things 2025-01-26 02:15:37 +01:00
clizia
f66600cabc idk girl this is strange 2025-01-12 23:23:34 +01:00
clizia
abfc03434c added petname generator for lobby id 2025-01-11 00:12:32 +01:00
clizia
ed8fbcf70c it is now possible to connect and create a player 2025-01-10 23:58:42 +01:00
clizia
24e9621194 made a simple echo chat server 2025-01-10 01:16:10 +01:00
clizia
ebaa596a2d Display for Suit and Card 2025-01-09 14:53:32 +01:00
clizia
cf4f15f509 implemented draw and made experimental version of players and lobby 2025-01-09 02:14:48 +01:00
15 changed files with 634 additions and 28 deletions

248
Cargo.lock generated
View file

@ -72,6 +72,17 @@ version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
[[package]]
name = "async-trait"
version = "0.1.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.4.0"
@ -99,6 +110,15 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bumpalo"
version = "3.16.0"
@ -130,6 +150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
@ -144,6 +165,18 @@ dependencies = [
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
@ -156,16 +189,55 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "cpufeatures"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "durak-frthistime"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"rand",
"petname",
"rand 0.9.0-beta.1",
"serde",
"serde_json",
"sha256",
"tokio",
]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "errno"
version = "0.3.10"
@ -176,6 +248,27 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.3.0-rc.0"
@ -197,12 +290,39 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "js-sys"
version = "0.3.76"
@ -305,6 +425,20 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "petname"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cd31dcfdbbd7431a807ef4df6edd6473228e94d5c805e8cf671227a21bad068"
dependencies = [
"anyhow",
"clap",
"itertools",
"proc-macro2",
"quote",
"rand 0.8.5",
]
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@ -338,17 +472,38 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8478de76992f2825a1052cc2ae9d1401cdb62687761d4100ddd69a73dc3dc48"
dependencies = [
"rand_chacha",
"rand_core",
"rand_chacha 0.9.0-beta.1",
"rand_core 0.9.0-beta.1",
"zerocopy 0.8.14",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0-beta.1"
@ -356,7 +511,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f16da77124f4ee9fabd55ce6540866e9101431863b4876de58b68797f331adf2"
dependencies = [
"ppv-lite86",
"rand_core",
"rand_core 0.9.0-beta.1",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.15",
]
[[package]]
@ -365,7 +529,7 @@ version = "0.9.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a98fa0b8309344136abe6244130311e76997e546f76fae8054422a7539b43df7"
dependencies = [
"getrandom",
"getrandom 0.3.0-rc.0",
"zerocopy 0.8.14",
]
@ -397,12 +561,74 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha256"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0"
dependencies = [
"async-trait",
"bytes",
"hex",
"sha2",
"tokio",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
@ -474,6 +700,12 @@ dependencies = [
"syn",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.14"
@ -486,6 +718,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"

View file

@ -3,8 +3,25 @@ name = "durak-frthistime"
version = "0.1.0"
edition = "2021"
[lib]
name = "lib"
path = "src/lib.rs"
[[bin]]
name = "server"
path = "src/bin/server.rs"
[[bin]]
name = "client"
path = "src/bin/client.rs"
[dependencies]
rand = "0.9.0-beta.1"
clap = "4.5.23"
tokio = { version = "1.42.0", features = ["full"] }
anyhow = "1.0.95"
serde_json = "1.0.135"
serde = { version = "1.0.217", features = ["derive"] }
sha256 = "1.5.0"
petname = "2.0.2"
crossterm = "0.28.1"

15
src/bin/client.rs Normal file
View file

@ -0,0 +1,15 @@
use lib::{client::Client, message::Message};
#[tokio::main]
pub async fn main() -> anyhow::Result<()> {
let mut client = Client::connect("127.0.0.1", 8080).await?;
for i in 1..11 {
let message = Message::new(format!("Hello toto x {}!!!", i));
client.send_message(message.unwrap().clone()).await?;
}
client.send_message(Message::new("EXIT").unwrap()).await?;
Ok(())
}

8
src/bin/server.rs Normal file
View file

@ -0,0 +1,8 @@
use lib::server::Server;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut server = Server::new("127.0.0.1", 8080);
server.run().await?;
Ok(())
}

View file

@ -1,10 +1,14 @@
#[derive(Debug)]
use std::fmt::Display;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Clone)]
pub struct Card {
pub suit: Suit,
pub value: u8,
}
#[derive(Debug, Clone, Copy)]
#[derive(Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum Suit {
Hearts,
Diamonds,
@ -13,7 +17,7 @@ pub enum Suit {
}
impl Card {
pub fn new(suit: Suit, value: u8) -> Card {
pub fn new(suit: Suit, value: u8) -> Self {
Card {
suit,
value,
@ -28,3 +32,22 @@ impl Card {
self.value
}
}
impl Display for Suit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let suit = match self {
Suit::Diamonds => String::from(""),
Suit::Hearts => String::from(""),
Suit::Spades => String::from(""),
Suit::Clubs => String::from(""),
};
write!(f, "{}", suit)
}
}
impl Display for Card {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[{}{}]", self.value, self.suit)
}
}

28
src/client.rs Normal file
View file

@ -0,0 +1,28 @@
use tokio::{io::AsyncWriteExt, net::TcpStream};
use crate::message::Message;
pub struct Client {
pub server_host: String,
pub server_port: u16,
pub stream: TcpStream,
}
impl Client {
pub async fn connect(host: impl Into<String>, port: u16) -> anyhow::Result<Self> {
let host = host.into();
let address = format!("{}:{}", host, port);
let stream = TcpStream::connect(address).await?;
Ok(Self {
server_host: host,
server_port: port,
stream,
})
}
pub async fn send_message(&mut self, message: Message) -> anyhow::Result<()> {
self.stream.write_all(&message.encode()).await?;
Ok(())
}
}

5
src/constant.rs Normal file
View file

@ -0,0 +1,5 @@
pub const METADATA_SIZE: usize = 2;
pub const MESSAGE_KIND_MOVE: u8 = 0;
pub const MESSAGE_KIND_PLAYER_SETUP: u8 = 1;
pub const MESSAGE_KIND_LOBBY_SETUP: u8 = 2;

View file

@ -1,15 +1,16 @@
use crate::card::Card;
use crate::card::Suit;
use rand::seq::SliceRandom;
use rand::rng;
use crate::card::Card;
use crate::card::Suit;
#[derive(PartialEq, Eq, Hash, Clone)]
pub struct Deck {
pub deck: Vec<Card>,
}
impl Deck {
pub fn new() -> Deck {
pub fn new() -> Self {
// possible values go from 0 to 8 because Durak is played
// without cards with a value lower than 6 in real life
// and ace is the highest card
@ -34,14 +35,24 @@ impl Deck {
self.deck
}
pub fn shuffle(mut self) -> Deck {
pub fn shuffle(mut self) -> Self {
let mut rng = rng();
self.deck.shuffle(&mut rng); // shuffle modifies in place
self
}
pub fn draw(mut self) -> Card {
todo!()
pub fn draw(mut self, n: u8) -> Vec<Card> {
if n as usize > self.deck.len() {
let drawn: Vec<Card> = self.deck
.drain(0..)
.collect();
drawn
} else {
let drawn: Vec<Card> = self.deck
.drain(0..n as usize)
.collect();
drawn
}
}
}

9
src/lib.rs Normal file
View file

@ -0,0 +1,9 @@
pub mod server;
pub mod client;
pub mod card;
pub mod deck;
pub mod lobby;
pub mod player;
pub mod message;
pub mod message_read;
pub mod constant;

40
src/lobby.rs Normal file
View file

@ -0,0 +1,40 @@
use crate::{deck::Deck, player::Player};
use petname::Generator;
#[derive(Eq, PartialEq, Hash, Clone)]
pub struct Lobby {
pub id: String,
pub players: Vec<Player>,
pub deck: Deck,
}
impl Lobby {
pub fn new() -> Self {
let players: Vec<Player> = Vec::new();
let deck = Deck::new().shuffle();
let petname = petname::Petnames::default().generate_one(2, "-").expect("no words provided");
Lobby {
id: petname,
players,
deck,
}
}
pub fn join_lobby(mut self, player: Player) {
self.players.push(player);
}
pub fn get_players(self) -> Vec<Player> {
self.players
}
pub fn get_deck(self) -> Deck {
self.deck
}
pub fn get_id(&self) -> String {
self.id.clone()
}
}

View file

@ -1,22 +1,68 @@
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};
use tokio::io::AsyncWriteExt;
use deck::Deck;
async fn handle_connection(mut stream: TcpStream, addr: SocketAddr) -> (Option<Player>, Option<Lobby>) {
let (mut read, mut write) = stream.split();
mod card;
mod deck;
mod player;
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() -> Result<(), anyhow::Error> {
let listener = TcpListener::bind("127.0.0.1:6379").await?;
async fn main() -> io::Result<()> {
let address = "127.0.0.1:8080".to_string();
let listener = TcpListener::bind(&address).await?;
let mut lobbies: Arc<Mutex<HashMap<String, Lobby>>> = Arc::new(Mutex::new(HashMap::new()));
loop {
match listener.accept().await {
Ok((_socket, addr)) => println!("new client: {:?}", addr),
Err(e) => println!("couldn't get client: {:?}", e),
}
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(())

54
src/message.rs Normal file
View file

@ -0,0 +1,54 @@
use crate::constant::METADATA_SIZE;
// everything here needs to be adjusted for the deserialized json
//
#[derive(Debug, Clone)]
pub struct Message {
pub message_kind: MessageKind,
pub length: u16,
pub content: String,
}
// idk i just want to layout something, really didn't think much
#[derive(Debug, Clone)]
pub enum MessageKind {
Move(u8),
PlayerSetup(u8),
LobbySetup(u8),
}
impl Message {
pub fn new(content: impl Into<String>) -> anyhow::Result<Self> {
let content = content.into();
let length = content.len() as u16;
// add message kind to constructor
Ok(Self {
length,
content,
})
}
pub fn encode(&self) -> Vec<u8> {
let mut buffer = Vec::new();
buffer.extend(&self.length.to_be_bytes());
buffer.extend(self.content.as_bytes());
buffer
}
pub fn decode(buffer: &[u8]) -> anyhow::Result<Self> {
if buffer.len() < METADATA_SIZE {
return Err(anyhow::anyhow!("Invalid message length"));
}
let length = u16::from_be_bytes([buffer[0], buffer[1]]);
let content = String::from_utf8(buffer[2..2 + length as usize].to_vec())?;
// add message kind to constructor
Ok(Self {
length,
content,
})
}
}

42
src/message_read.rs Normal file
View file

@ -0,0 +1,42 @@
// add message kind everywhere is needed
use crate::{constant::METADATA_SIZE, message::Message};
pub struct MessageReader {
pub buffer: Vec<u8>,
}
impl MessageReader {
pub fn new() -> Self {
Self { buffer: Vec::new() }
}
fn can_parse(&self) -> bool {
if self.buffer.len() < METADATA_SIZE {
return false;
}
let length = u16::from_be_bytes([self.buffer[0], self.buffer[1]]);
self.buffer.len() >= METADATA_SIZE + length as usize
}
fn parse_first(&mut self) -> anyhow::Result<Message> {
let length = u16::from_be_bytes([self.buffer[0], self.buffer[1]]);
let message_length = METADATA_SIZE + length as usize;
let message = self.buffer[..message_length].to_vec();
self.buffer = self.buffer[message_length..].to_vec();
Message::decode(&message)
}
pub fn read(&mut self, data: &[u8]) -> anyhow::Result<Vec<Message>> {
self.buffer.extend_from_slice(data);
let mut data = vec![];
while self.can_parse() {
let message = self.parse_first()?;
data.push(message);
}
Ok(data)
}
}

View file

@ -1,20 +1,36 @@
use std::net::SocketAddr;
use serde::{Deserialize, Serialize};
use sha256::digest;
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<Card>,
}
impl Player {
pub fn new(addr: SocketAddr, name: &str) -> Player {
todo!()
pub fn new(addr: SocketAddr, name: &str) -> Self {
let hand_empty: Vec<Card> = Vec::new();
let to_digest: String = addr.to_string();
let id = digest(to_digest);
Player {
addr,
id,
name: name.to_string(),
hand: hand_empty,
}
}
pub fn get_addr(self) -> SocketAddr {

54
src/server.rs Normal file
View file

@ -0,0 +1,54 @@
use tokio::{io::AsyncReadExt, net::TcpListener};
use crate::message_read::MessageReader;
pub struct Server {
pub host: String,
pub port: u16,
}
impl Server {
pub fn new(host: impl Into<String>, port: u16) -> Self {
Server {
host: host.into(),
port,
}
}
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 socket, addr) = listener.accept().await?;
println!("Connection received from {}", addr);
tokio::task::spawn(async move {
let mut message_reader = MessageReader::new();
'handler: loop {
let mut buffer = vec![0; 256];
let bytes_read = socket.read(&mut buffer).await?;
let messages = message_reader.read(&buffer[..bytes_read])?;
for message in messages {
if message.content == "EXIT" {
println!("Connection closed by the client");
break 'handler;
}
println!("Message:\n{:?}", message);
}
}
Ok::<(), anyhow::Error>(())
});
}
Ok(())
}
}