odyssey-server/src/network.rs

95 lines
2.2 KiB
Rust

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(),
});
}
}