1
0
mirror of https://github.com/actix/examples synced 2025-02-13 05:52:20 +01:00

79 lines
2.3 KiB
Rust
Raw Normal View History

2019-03-09 18:03:09 -08:00
use std::time::{Duration, Instant};
2018-09-27 22:37:19 +03:00
use actix::prelude::*;
2019-03-18 05:31:32 -07:00
use actix_web_actors::ws;
2018-09-27 22:37:19 +03:00
/// How often heartbeat pings are sent
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
2022-02-18 01:44:53 +00:00
2018-09-27 22:37:19 +03:00
/// How long before lack of client response causes a timeout
const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
/// websocket connection is long running connection, it easier
/// to handle with an actor
2022-02-18 01:44:53 +00:00
pub struct MyWebSocket {
2018-09-27 22:37:19 +03:00
/// Client must send ping at least once per 10 seconds (CLIENT_TIMEOUT),
/// otherwise we drop connection.
hb: Instant,
}
2022-02-18 01:44:53 +00:00
impl MyWebSocket {
pub fn new() -> Self {
Self { hb: Instant::now() }
}
/// helper method that sends ping to client every second.
///
/// also this method checks heartbeats from client
fn hb(&self, ctx: &mut <Self as Actor>::Context) {
ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
// check client heartbeats
if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT {
// heartbeat timed out
println!("Websocket Client heartbeat failed, disconnecting!");
// stop actor
ctx.stop();
// don't try to send a ping
return;
}
ctx.ping(b"");
});
}
}
impl Actor for MyWebSocket {
type Context = ws::WebsocketContext<Self>;
2018-09-27 22:37:19 +03:00
/// Method is called on actor start. We start the heartbeat process here.
fn started(&mut self, ctx: &mut Self::Context) {
self.hb(ctx);
}
}
/// Handler for `ws::Message`
2019-12-16 11:23:36 +06:00
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWebSocket {
2022-02-18 02:44:02 +00:00
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
// process websocket messages
println!("WS: {:?}", msg);
match msg {
2019-12-16 11:23:36 +06:00
Ok(ws::Message::Ping(msg)) => {
2018-09-27 22:37:19 +03:00
self.hb = Instant::now();
ctx.pong(&msg);
}
2019-12-16 11:23:36 +06:00
Ok(ws::Message::Pong(_)) => {
self.hb = Instant::now();
}
2019-12-16 11:23:36 +06:00
Ok(ws::Message::Text(text)) => ctx.text(text),
Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
Ok(ws::Message::Close(reason)) => {
ctx.close(reason);
ctx.stop();
}
2019-12-16 11:23:36 +06:00
_ => ctx.stop(),
}
}
}