154 lines
4.5 KiB
Rust
Raw Normal View History

2021-09-10 16:22:38 +08:00
use crate::{
config::{HEARTBEAT_INTERVAL, PING_TIMEOUT},
2021-12-06 21:47:21 +08:00
services::user::LoggedUser,
web_socket::{
entities::{Connect, Disconnect, Socket},
WsBizHandlers,
WsMessageAdaptor,
WsServer,
2021-09-10 16:22:38 +08:00
},
};
use actix::*;
2021-09-23 17:50:28 +08:00
use actix_web::web::Data;
2021-09-19 23:21:10 +08:00
use actix_web_actors::{ws, ws::Message::Text};
2021-09-23 17:50:28 +08:00
use bytes::Bytes;
2021-12-16 22:24:05 +08:00
use lib_ws::WSMessage;
use std::{convert::TryFrom, sync::Arc, time::Instant};
2021-09-30 17:24:02 +08:00
#[derive(Debug)]
pub struct WsUser {
inner: LoggedUser,
}
impl WsUser {
pub fn new(inner: LoggedUser) -> Self { Self { inner } }
pub fn id(&self) -> &str { &self.inner.user_id }
}
2021-08-19 08:36:30 +08:00
2021-09-24 16:02:17 +08:00
pub struct WsClientData {
pub(crate) user: Arc<WsUser>,
2021-09-24 16:02:17 +08:00
pub(crate) socket: Socket,
pub(crate) data: Bytes,
}
pub struct WsClient {
user: Arc<WsUser>,
2021-09-24 16:02:17 +08:00
server: Addr<WsServer>,
2021-09-23 17:50:28 +08:00
biz_handlers: Data<WsBizHandlers>,
2021-08-19 08:36:30 +08:00
hb: Instant,
}
2021-09-24 16:02:17 +08:00
impl WsClient {
2021-09-30 17:24:02 +08:00
pub fn new(user: WsUser, server: Addr<WsServer>, biz_handlers: Data<WsBizHandlers>) -> Self {
2021-08-19 08:36:30 +08:00
Self {
user: Arc::new(user),
2021-08-19 08:36:30 +08:00
server,
2021-09-23 17:50:28 +08:00
biz_handlers,
hb: Instant::now(),
2021-08-19 08:36:30 +08:00
}
}
fn hb(&self, ctx: &mut ws::WebsocketContext<Self>) {
2021-09-19 23:21:10 +08:00
ctx.run_interval(HEARTBEAT_INTERVAL, |client, ctx| {
if Instant::now().duration_since(client.hb) > PING_TIMEOUT {
client.server.do_send(Disconnect {
sid: client.user.id().into(),
2021-08-19 08:36:30 +08:00
});
ctx.stop();
2021-09-19 23:21:10 +08:00
} else {
ctx.ping(b"");
2021-08-19 08:36:30 +08:00
}
});
}
2021-09-24 16:02:17 +08:00
fn handle_binary_message(&self, bytes: Bytes, socket: Socket) {
// TODO: ok to unwrap?
2021-12-16 22:24:05 +08:00
let message: WSMessage = WSMessage::try_from(bytes).unwrap();
match self.biz_handlers.get(&message.module) {
None => {
log::error!("Can't find the handler for {:?}", message.module);
},
2021-09-24 16:02:17 +08:00
Some(handler) => {
let client_data = WsClientData {
user: self.user.clone(),
2021-09-24 16:02:17 +08:00
socket,
data: Bytes::from(message.data),
};
2021-12-11 17:48:39 +08:00
handler.receive(client_data);
2021-09-24 16:02:17 +08:00
},
}
2021-08-19 08:36:30 +08:00
}
}
2021-09-24 16:02:17 +08:00
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for WsClient {
2021-08-19 08:36:30 +08:00
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
match msg {
Ok(ws::Message::Ping(msg)) => {
self.hb = Instant::now();
ctx.pong(&msg);
},
2021-09-22 14:42:14 +08:00
Ok(ws::Message::Pong(_msg)) => {
2021-11-03 15:37:38 +08:00
// tracing::debug!("Receive {} pong {:?}", &self.session_id, &msg);
2021-08-19 08:36:30 +08:00
self.hb = Instant::now();
},
2021-09-23 17:50:28 +08:00
Ok(ws::Message::Binary(bytes)) => {
2021-09-24 16:02:17 +08:00
let socket = ctx.address().recipient();
self.handle_binary_message(bytes, socket);
2021-08-19 08:36:30 +08:00
},
2021-09-19 23:21:10 +08:00
Ok(Text(_)) => {
log::warn!("Receive unexpected text message");
},
2021-08-19 08:36:30 +08:00
Ok(ws::Message::Close(reason)) => {
ctx.close(reason);
ctx.stop();
},
2021-09-19 23:21:10 +08:00
Ok(ws::Message::Continuation(_)) => {},
Ok(ws::Message::Nop) => {},
2021-08-19 08:36:30 +08:00
Err(e) => {
log::error!("[{}]: WebSocketStream protocol error {:?}", self.user.id(), e);
2021-08-19 08:36:30 +08:00
ctx.stop();
},
}
}
}
2021-09-24 16:02:17 +08:00
impl Handler<WsMessageAdaptor> for WsClient {
2021-08-19 08:36:30 +08:00
type Result = ();
2021-09-24 16:02:17 +08:00
fn handle(&mut self, msg: WsMessageAdaptor, ctx: &mut Self::Context) { ctx.binary(msg.0); }
2021-08-19 08:36:30 +08:00
}
2021-09-23 17:50:28 +08:00
2021-09-24 16:02:17 +08:00
impl Actor for WsClient {
2021-09-23 17:50:28 +08:00
type Context = ws::WebsocketContext<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
self.hb(ctx);
let socket = ctx.address().recipient();
let connect = Connect {
socket,
sid: self.user.id().into(),
2021-09-23 17:50:28 +08:00
};
self.server
.send(connect)
.into_actor(self)
.then(|res, _client, _ctx| {
match res {
2021-11-03 15:37:38 +08:00
Ok(Ok(_)) => tracing::trace!("Send connect message to server success"),
2021-09-23 17:50:28 +08:00
Ok(Err(e)) => log::error!("Send connect message to server failed: {:?}", e),
Err(e) => log::error!("Send connect message to server failed: {:?}", e),
}
fut::ready(())
})
.wait(ctx);
}
fn stopping(&mut self, _: &mut Self::Context) -> Running {
self.server.do_send(Disconnect {
sid: self.user.id().into(),
2021-09-23 17:50:28 +08:00
});
Running::Stop
}
}