Compare commits
No commits in common. "fbaf386ebb65b5fe55e0cdc096e264cd47054b53" and "09c5fe3d8b57d9e305f14045d776dd10b8f6ff51" have entirely different histories.
fbaf386ebb
...
09c5fe3d8b
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -2,15 +2,6 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aho-corasick"
|
|
||||||
version = "0.7.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -171,8 +162,6 @@ dependencies = [
|
|||||||
name = "hexland-server"
|
name = "hexland-server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand",
|
|
||||||
"regex",
|
|
||||||
"sha2",
|
"sha2",
|
||||||
"tungstenite",
|
"tungstenite",
|
||||||
]
|
]
|
||||||
@ -240,12 +229,6 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "native-tls"
|
name = "native-tls"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
@ -390,23 +373,6 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex"
|
|
||||||
version = "1.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
|
||||||
dependencies = [
|
|
||||||
"aho-corasick",
|
|
||||||
"memchr",
|
|
||||||
"regex-syntax",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-syntax"
|
|
||||||
version = "0.6.27"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remove_dir_all"
|
name = "remove_dir_all"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -7,6 +7,4 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tungstenite = { version = "0.17.3", features = ["native-tls"] }
|
tungstenite = { version = "0.17.3", features = ["native-tls"] }
|
||||||
sha2 = "0.10.6"
|
sha2 = "0.10.6"
|
||||||
rand = "0.8.5"
|
|
||||||
regex = "1.6.0"
|
|
65
src/main.rs
65
src/main.rs
@ -1,61 +1,42 @@
|
|||||||
use std::net::TcpListener;
|
use std::net::TcpListener;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
mod message;
|
use tungstenite::protocol::Message;
|
||||||
use message::Message;
|
|
||||||
|
|
||||||
use rand::RngCore;
|
|
||||||
|
|
||||||
use tungstenite::protocol::Message as WsMessage;
|
|
||||||
|
|
||||||
use sha2::{Sha256, Digest};
|
use sha2::{Sha256, Digest};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let code_generator = Arc::new(Mutex::new(CodeGenerator::default()));
|
let code_generator = Arc::new(Mutex::new(CodeGenerator {
|
||||||
|
counter: 0,
|
||||||
|
salt: [0; 32], // TODO have this be randomized on startup
|
||||||
|
}));
|
||||||
let server = TcpListener::bind("127.0.0.1:8080").unwrap();
|
let server = TcpListener::bind("127.0.0.1:8080").unwrap();
|
||||||
|
|
||||||
let rooms = Arc::new(Mutex::new(HashMap::new()));
|
|
||||||
|
|
||||||
for stream in server.incoming() {
|
for stream in server.incoming() {
|
||||||
let code_generator = Arc::clone(&code_generator);
|
thread::spawn ( { let code_generator = Arc::clone(&code_generator); move || {
|
||||||
let rooms = Arc::clone(&rooms);
|
|
||||||
thread::spawn (move || {
|
|
||||||
let mut ws = tungstenite::accept(stream.unwrap()).unwrap();
|
let mut ws = tungstenite::accept(stream.unwrap()).unwrap();
|
||||||
println!("New client!");
|
println!("New client!");
|
||||||
ws.write_message(WsMessage::Text("HOSTJOIN:".to_string())).unwrap();
|
ws.write_message(Message::Text("HOSTJOIN:".to_string())).unwrap();
|
||||||
loop {
|
loop {
|
||||||
let message = ws.read_message();
|
let message = ws.read_message();
|
||||||
println!("{:?}", message);
|
println!("{:?}", message);
|
||||||
match message {
|
match message {
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
Ok(WsMessage::Close(_)) => break,
|
Ok(Message::Text(msg)) =>
|
||||||
Ok(WsMessage::Text(msg)) => {
|
match msg.as_str().trim() {
|
||||||
let msg = Message::parse(msg.as_str().trim());
|
"HOST:" => {
|
||||||
match msg {
|
ws.write_message(Message::Text(code_generator.lock().unwrap().generate())).unwrap();
|
||||||
Ok(msg) =>
|
},
|
||||||
match msg.command {
|
_ => unimplemented!(),
|
||||||
"HOST" => {
|
},
|
||||||
let code = code_generator.lock().unwrap().generate();
|
|
||||||
let mut room = Room::default();
|
|
||||||
let player = Player { name: "Guest".to_string() };
|
|
||||||
room.players.push(player);
|
|
||||||
rooms.lock().unwrap().insert(code.clone(), room);
|
|
||||||
ws.write_message(WsMessage::Text(code)).unwrap();
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
|
||||||
Err(_) => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Default)]
|
|
||||||
struct Room {
|
struct Room {
|
||||||
players: Vec<Player>,
|
players: Vec<Player>,
|
||||||
}
|
}
|
||||||
@ -81,15 +62,3 @@ impl CodeGenerator {
|
|||||||
format!("{:x}", hasher.finalize())[..6].to_string()
|
format!("{:x}", hasher.finalize())[..6].to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CodeGenerator {
|
|
||||||
fn default() -> Self {
|
|
||||||
let mut salt = [0; 32];
|
|
||||||
rand::thread_rng().fill_bytes(&mut salt);
|
|
||||||
|
|
||||||
CodeGenerator {
|
|
||||||
counter: 0,
|
|
||||||
salt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
#[derive(PartialEq, Debug)]
|
|
||||||
pub struct Message<'a> {
|
|
||||||
pub command: &'a str,
|
|
||||||
pub args: Vec<&'a str>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
||||||
|
|
||||||
#[repr(u8)]
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
pub enum Error {
|
|
||||||
BadParse,
|
|
||||||
UnknownCommand,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Message<'a> {
|
|
||||||
pub fn parse(text: &'a str) -> Result<Message<'a>> {
|
|
||||||
let re = regex::Regex::new(r"^([A-Z_]+):\s*(.*)").unwrap();
|
|
||||||
match re.captures(text) {
|
|
||||||
Some(captures) => {
|
|
||||||
if captures.len() < 3 {
|
|
||||||
Err(Error::BadParse)
|
|
||||||
} else {
|
|
||||||
let command = captures.get(1).unwrap().as_str();
|
|
||||||
let args = captures.get(2).unwrap().as_str()
|
|
||||||
.split(',')
|
|
||||||
.map(|s| s.trim())
|
|
||||||
.collect();
|
|
||||||
Ok(Message { command, args })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => Err(Error::BadParse),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
#[test]
|
|
||||||
fn test_parse() -> Result<()> {
|
|
||||||
let text = "COMMAND: arg1, arg2";
|
|
||||||
let msg = Message::parse(text)?;
|
|
||||||
assert_eq!(Message {
|
|
||||||
command: "COMMAND",
|
|
||||||
args: vec!["arg1", "arg2"],
|
|
||||||
}, msg);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user