@@ -45,6 +45,12 @@ use y_sweet_core::{
4545
4646const PLANE_VERIFIED_USER_DATA_HEADER : & str = "x-verified-user-data" ;
4747
48+ // Every 20 seconds, we send a ping to the client.
49+ const PING_EVERY : Duration = Duration :: from_secs ( 20 ) ;
50+ // If we haven't received a pong in the last 40 seconds, we close the connection.
51+ // All modern browsers will respond to websocket pings with a pong message.
52+ const PONG_TIMEOUT : Duration = Duration :: from_secs ( 40 ) ;
53+
4854fn current_time_epoch_millis ( ) -> u64 {
4955 let now = std:: time:: SystemTime :: now ( ) ;
5056 let duration_since_epoch = now. duration_since ( std:: time:: UNIX_EPOCH ) . unwrap ( ) ;
@@ -600,9 +606,26 @@ async fn handle_socket(
600606 let ( mut sink, mut stream) = socket. split ( ) ;
601607 let ( send, mut recv) = channel ( 1024 ) ;
602608
609+ let last_pong = Arc :: new ( RwLock :: new ( tokio:: time:: Instant :: now ( ) ) ) ;
610+ let last_pong_clone = last_pong. clone ( ) ;
611+
603612 tokio:: spawn ( async move {
604- while let Some ( msg) = recv. recv ( ) . await {
605- let _ = sink. send ( Message :: Binary ( msg) ) . await ;
613+ let mut ticker = tokio:: time:: interval ( PING_EVERY ) ;
614+ ticker. set_missed_tick_behavior ( tokio:: time:: MissedTickBehavior :: Delay ) ;
615+
616+ loop {
617+ tokio:: select! {
618+ Some ( msg) = recv. recv( ) => {
619+ let _ = sink. send( Message :: Binary ( msg) ) . await ;
620+ }
621+ _ = ticker. tick( ) => {
622+ if last_pong_clone. read( ) . expect( "Failed to get read lock on last_pong" ) . elapsed( ) > PONG_TIMEOUT {
623+ tracing:: info!( "Pong timeout, closing connection" ) ;
624+ break ;
625+ }
626+ let _ = sink. send( Message :: Ping ( vec![ ] ) ) . await ;
627+ }
628+ }
606629 }
607630 } ) ;
608631
@@ -618,6 +641,10 @@ async fn handle_socket(
618641 let msg = match msg {
619642 Ok ( Message :: Binary ( bytes) ) => bytes,
620643 Ok ( Message :: Close ( _) ) => break ,
644+ Ok ( Message :: Pong ( _) ) => {
645+ * last_pong. write( ) . expect( "Failed to get write lock on last_pong" ) = tokio:: time:: Instant :: now( ) ;
646+ continue ;
647+ }
621648 Err ( _e) => {
622649 // The stream will complain about things like
623650 // connections being lost without handshake.
0 commit comments