162 lines
4.5 KiB
Rust
Raw Normal View History

2021-08-19 08:36:30 +08:00
use crate::{
config::{HEARTBEAT_INTERVAL, PING_TIMEOUT},
2021-08-19 14:08:24 +08:00
ws_service::{
2021-08-19 08:36:30 +08:00
entities::{Connect, Disconnect, SessionId},
2021-08-19 14:08:24 +08:00
ClientMessage,
MessageData,
2021-08-19 08:36:30 +08:00
WSServer,
},
};
use actix::{
fut,
Actor,
ActorContext,
ActorFuture,
Addr,
AsyncContext,
ContextFutureSpawner,
Handler,
Running,
StreamHandler,
WrapFuture,
};
use actix_web_actors::{ws, ws::Message::Text};
use std::time::Instant;
2021-08-19 14:08:24 +08:00
pub struct WSClient {
2021-08-19 08:36:30 +08:00
sid: SessionId,
server: Addr<WSServer>,
hb: Instant,
}
2021-08-19 14:08:24 +08:00
impl WSClient {
2021-08-19 08:36:30 +08:00
pub fn new(sid: SessionId, server: Addr<WSServer>) -> Self {
Self {
sid,
hb: Instant::now(),
server,
}
}
fn hb(&self, ctx: &mut ws::WebsocketContext<Self>) {
ctx.run_interval(HEARTBEAT_INTERVAL, |ws_session, ctx| {
if Instant::now().duration_since(ws_session.hb) > PING_TIMEOUT {
ws_session.server.do_send(Disconnect {
sid: ws_session.sid.clone(),
});
ctx.stop();
return;
}
ctx.ping(b"");
});
}
2021-08-19 14:08:24 +08:00
fn send(&self, data: MessageData) {
let msg = ClientMessage::new(self.sid.clone(), data);
self.server.do_send(msg);
}
}
impl Actor for WSClient {
type Context = ws::WebsocketContext<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
2021-08-19 08:36:30 +08:00
self.hb(ctx);
let socket = ctx.address().recipient();
let connect = Connect {
socket,
sid: self.sid.clone(),
};
self.server
.send(connect)
.into_actor(self)
.then(|res, _ws_session, _ctx| {
match res {
Ok(Ok(_)) => {},
Ok(Err(_e)) => {
unimplemented!()
},
Err(_e) => unimplemented!(),
}
fut::ready(())
})
.wait(ctx);
}
fn stopping(&mut self, _: &mut Self::Context) -> Running {
self.server.do_send(Disconnect {
sid: self.sid.clone(),
});
Running::Stop
}
}
2021-08-19 14:08:24 +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)) => {
log::debug!("Receive {} ping {:?}", &self.sid, &msg);
self.hb = Instant::now();
ctx.pong(&msg);
},
Ok(ws::Message::Pong(msg)) => {
log::debug!("Receive {} pong {:?}", &self.sid, &msg);
2021-08-19 14:08:24 +08:00
self.send(MessageData::Connect(self.sid.clone()));
2021-08-19 08:36:30 +08:00
self.hb = Instant::now();
},
Ok(ws::Message::Binary(bin)) => {
log::debug!(" Receive {} binary", &self.sid);
2021-08-19 14:08:24 +08:00
self.send(MessageData::Binary(bin));
2021-08-19 08:36:30 +08:00
},
Ok(ws::Message::Close(reason)) => {
log::debug!("Receive {} close {:?}", &self.sid, &reason);
ctx.close(reason);
ctx.stop();
},
Ok(ws::Message::Continuation(c)) => {
log::debug!("Receive {} continues message {:?}", &self.sid, &c);
},
Ok(ws::Message::Nop) => {
log::debug!("Receive Nop message");
},
Ok(Text(s)) => {
log::debug!("Receive {} text {:?}", &self.sid, &s);
2021-08-19 14:08:24 +08:00
self.send(MessageData::Text(s));
2021-08-19 08:36:30 +08:00
},
Err(e) => {
let msg = format!("{} error: {:?}", &self.sid, e);
ctx.text(&msg);
log::error!("stream {}", msg);
ctx.stop();
},
}
}
}
2021-08-19 14:08:24 +08:00
impl Handler<ClientMessage> for WSClient {
2021-08-19 08:36:30 +08:00
type Result = ();
2021-08-19 14:08:24 +08:00
fn handle(&mut self, msg: ClientMessage, ctx: &mut Self::Context) {
match msg.data {
MessageData::Text(text) => {
2021-08-19 08:36:30 +08:00
ctx.text(text);
},
2021-08-19 14:08:24 +08:00
MessageData::Binary(binary) => {
2021-08-19 08:36:30 +08:00
ctx.binary(binary);
},
2021-08-19 14:08:24 +08:00
MessageData::Connect(sid) => {
2021-08-19 08:36:30 +08:00
let connect_msg = format!("{} connect", &sid);
ctx.text(connect_msg);
},
2021-08-19 14:08:24 +08:00
MessageData::Disconnect(text) => {
2021-08-19 08:36:30 +08:00
log::debug!("Session start disconnecting {}", self.sid);
ctx.text(text);
ctx.stop();
},
}
}
}