1- use crate :: error:: RSocketError ;
1+ use crate :: error:: { RSocketError , ERR_CONN_CLOSED } ;
22use crate :: frame:: { self , Frame } ;
33use crate :: payload:: { Payload , SetupPayload , SetupPayloadBuilder } ;
44use crate :: runtime;
@@ -7,7 +7,7 @@ use crate::transport::{
77 self , Acceptor , Connection , DuplexSocket , Reader , Splitter , Transport , Writer ,
88} ;
99use crate :: Result ;
10- use futures:: { future, FutureExt , SinkExt , StreamExt } ;
10+ use futures:: { future, select , FutureExt , SinkExt , StreamExt } ;
1111use std:: error:: Error ;
1212use std:: net:: SocketAddr ;
1313use std:: pin:: Pin ;
@@ -115,6 +115,7 @@ where
115115 } ;
116116
117117 let ( snd_tx, mut snd_rx) = mpsc:: channel :: < Frame > ( super :: CHANNEL_SIZE ) ;
118+ let cloned_snd_tx = snd_tx. clone ( ) ;
118119 let mut socket = DuplexSocket :: new ( 1 , snd_tx, splitter) . await ;
119120
120121 let mut cloned_socket = socket. clone ( ) ;
@@ -126,15 +127,40 @@ where
126127 let conn = tp. connect ( ) . await ?;
127128 let ( mut sink, mut stream) = conn. split ( ) ;
128129
130+ let setup = self . setup . build ( ) ;
131+
132+ // begin write loop
133+ let tick_period = setup. keepalive_interval ( ) ;
129134 runtime:: spawn ( async move {
130- while let Some ( frame) = snd_rx. next ( ) . await {
131- if let Err ( e) = ( & mut sink) . write ( frame) . await {
132- error ! ( "write frame failed: {}" , e) ;
133- break ;
135+ loop {
136+ // send keepalive if timeout
137+ match tokio:: time:: timeout ( tick_period, snd_rx. next ( ) ) . await {
138+ Ok ( Some ( frame) ) => {
139+ if let frame:: Body :: Error ( e) = frame. get_body_ref ( ) {
140+ if e. get_code ( ) == ERR_CONN_CLOSED {
141+ break ;
142+ }
143+ }
144+ if let Err ( e) = ( & mut sink) . write ( frame) . await {
145+ error ! ( "write frame failed: {}" , e) ;
146+ break ;
147+ }
148+ }
149+ Ok ( None ) => break ,
150+ Err ( _) => {
151+ // keepalive
152+ let keepalive_frame =
153+ frame:: Keepalive :: builder ( 0 , Frame :: FLAG_RESPOND ) . build ( ) ;
154+ if let Err ( e) = ( & mut sink) . write ( keepalive_frame) . await {
155+ error ! ( "write frame failed: {}" , e) ;
156+ break ;
157+ }
158+ }
134159 }
135160 }
136161 } ) ;
137162
163+ // begin read loop
138164 let closer = self . closer . take ( ) ;
139165 runtime:: spawn ( async move {
140166 while let Some ( next) = stream. read ( ) . await {
@@ -151,12 +177,22 @@ where
151177 }
152178 }
153179 }
180+
181+ // workaround: send a notify frame that the connection has been closed.
182+ let close_frame = frame:: Error :: builder ( 0 , 0 )
183+ . set_code ( ERR_CONN_CLOSED )
184+ . build ( ) ;
185+ if let Err ( _) = cloned_snd_tx. send ( close_frame) . await {
186+ debug ! ( "send close notify frame failed!" ) ;
187+ }
188+
189+ // invoke on_close handler
154190 if let Some ( mut invoke) = closer {
155191 invoke ( ) ;
156192 }
157193 } ) ;
158194
159- socket. setup ( self . setup . build ( ) ) . await ;
195+ socket. setup ( setup) . await ;
160196 Ok ( Client :: from ( socket) )
161197 }
162198}
0 commit comments