Refactor network into module, add connection event

This commit is contained in:
Hamcha 2020-10-02 11:37:08 +02:00
parent f63c184d13
commit f3e200e91d
Signed by: hamcha
GPG key ID: 41467804B19A3315
4 changed files with 109 additions and 51 deletions

1
Cargo.lock generated
View file

@ -902,6 +902,7 @@ dependencies = [
"env_logger", "env_logger",
"futures-util", "futures-util",
"log", "log",
"rand",
"serde 1.0.116", "serde 1.0.116",
"serde_derive", "serde_derive",
"shipyard", "shipyard",

View file

@ -5,15 +5,16 @@ authors = ["Hamcha <hamcha@crunchy.rocks>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
tungstenite = "0.11" actix = "0.10"
shipyard = { version = "0.4", features = ["parallel", "serde"] }
config = "0.10" config = "0.10"
serde = { version = "1", features = ["derive"] } env_logger = "0.7"
serde_derive = "1"
tokio = { version = "0.2", features = ["full"] }
tokio-tungstenite = "0.11"
futures-util = { version = "0.3", default-features = false, features = ["async-await", "sink", "std"] } futures-util = { version = "0.3", default-features = false, features = ["async-await", "sink", "std"] }
log = { version = "0.4", features = ["std", "serde"] } log = { version = "0.4", features = ["std", "serde"] }
rand = "0.7"
serde = { version = "1", features = ["derive"] }
serde_derive = "1"
shipyard = { version = "0.4", features = ["parallel", "serde"] }
tokio = { version = "0.2", features = ["full"] }
tokio-tungstenite = "0.11"
tungstenite = "0.11"
ultraviolet = { version = "0.7", features = [ "f64", "int", "serde" ] } ultraviolet = { version = "0.7", features = [ "f64", "int", "serde" ] }
env_logger = "0.7"
actix = "0.10"

View file

@ -1,15 +1,14 @@
mod components; mod components;
mod config; mod config;
mod network;
mod systems; mod systems;
use crate::config::Settings; use crate::config::Settings;
use crate::network::{listen_websocket, NetworkManager};
use actix::prelude::*; use actix::prelude::*;
use env_logger::Env; use env_logger::Env;
use log::info;
use shipyard::World; use shipyard::World;
use std::time::Duration; use std::time::Duration;
use tokio::net::{TcpListener, TcpStream};
use tokio_tungstenite::WebSocketStream;
// Minimum delay between updates, in milliseconds // Minimum delay between updates, in milliseconds
const MIN_UPDATE_MS: u64 = 10; const MIN_UPDATE_MS: u64 = 10;
@ -29,24 +28,6 @@ impl Actor for Game {
} }
} }
struct NetworkConnection {
stream: WebSocketStream<TcpStream>,
}
impl Actor for NetworkConnection {
type Context = Context<NetworkConnection>;
fn started(&mut self, _ctx: &mut Self::Context) {
//TODO Read
}
}
struct NetworkManager {}
impl Actor for NetworkManager {
type Context = Context<NetworkManager>;
}
fn main() { fn main() {
let env = Env::default().filter_or("LOG_LEVEL", "info"); let env = Env::default().filter_or("LOG_LEVEL", "info");
env_logger::init_from_env(env); env_logger::init_from_env(env);
@ -54,6 +35,7 @@ fn main() {
let settings = Settings::new().unwrap(); let settings = Settings::new().unwrap();
let system = System::new("main"); let system = System::new("main");
Game::create(|_ctx| { Game::create(|_ctx| {
// Create world // Create world
let world = World::default(); let world = World::default();
@ -64,27 +46,7 @@ fn main() {
Game { world } Game { world }
}); });
Arbiter::spawn(listen_websocket(settings.bind)); NetworkManager::new(settings.bind).start();
system.run().unwrap(); system.run().unwrap();
} }
async fn listen_websocket(bind: String) {
let try_socket = TcpListener::bind(&bind).await;
let mut listener = try_socket.expect("Failed to bind");
info!("Listening on: {}", bind);
while let Ok((stream, _)) = listener.accept().await {
let addr = stream
.peer_addr()
.expect("connected streams should have a peer address");
info!("Peer address: {}", addr);
let stream = tokio_tungstenite::accept_async(stream)
.await
.expect("Error during the websocket handshake occurred");
info!("New WebSocket connection: {}", addr);
NetworkConnection::create(|_ctx| NetworkConnection { stream });
}
}

94
src/network.rs Normal file
View file

@ -0,0 +1,94 @@
use actix::prelude::*;
use log::info;
use rand::prelude::*;
use std::collections::HashMap;
use tokio::net::{TcpListener, TcpStream};
use tokio_tungstenite::WebSocketStream;
pub struct NetworkConnection {
conn_id: u64,
connected: bool,
stream: WebSocketStream<TcpStream>,
manager: Addr<NetworkManager>,
}
impl Actor for NetworkConnection {
type Context = Context<NetworkConnection>;
fn started(&mut self, ctx: &mut Self::Context) {
// Send manager my info and get a connection ID assigned
let addr = ctx.address();
self.manager
.send(ClientConnected { addr })
.into_actor(self)
.then(move |res, act, _| {
act.conn_id = res.unwrap();
act.connected = true;
async {}.into_actor(act)
})
.wait(ctx);
//TODO Start recv/send loop
}
}
#[derive(Message)]
#[rtype(result = "u64")]
struct ClientConnected {
addr: Addr<NetworkConnection>,
}
pub struct NetworkManager {
bind: String,
clients: HashMap<u64, Addr<NetworkConnection>>,
}
impl Actor for NetworkManager {
type Context = Context<NetworkManager>;
fn started(&mut self, ctx: &mut Self::Context) {
Arbiter::spawn(listen_websocket(self.bind.clone(), ctx.address()));
}
}
impl Handler<ClientConnected> for NetworkManager {
type Result = u64;
fn handle(&mut self, msg: ClientConnected, _ctx: &mut Self::Context) -> Self::Result {
let client_id = rand::thread_rng().gen();
self.clients.insert(client_id, msg.addr);
client_id
}
}
impl NetworkManager {
pub fn new(bind: String) -> Self {
NetworkManager {
bind,
clients: HashMap::new(),
}
}
}
pub async fn listen_websocket(bind: String, manager: Addr<NetworkManager>) {
let try_socket = TcpListener::bind(&bind).await;
let mut listener = try_socket.expect("Failed to bind");
info!("Listening on: {}", bind);
while let Ok((stream, _)) = listener.accept().await {
let addr = stream
.peer_addr()
.expect("connected streams should have a peer address");
info!("Peer address: {}", addr);
let stream = tokio_tungstenite::accept_async(stream)
.await
.expect("Error during the websocket handshake occurred");
info!("New WebSocket connection: {}", addr);
NetworkConnection::create(|_ctx| NetworkConnection {
conn_id: 0,
connected: false,
stream,
manager: manager.clone(),
});
}
}