@@ -21,10 +21,11 @@ use p2p::{
2121
2222use crate :: {
2323 handshake:: { self , CompletedHandshake , ConnectionConfig } ,
24- ConnectionMetrics , Preferences , TimedMessage , TimedMessages ,
24+ ConnectionMetrics , OutboundPing , Preferences , TimedMessage , TimedMessages ,
2525} ;
2626
2727pub const READ_TIMEOUT : Duration = Duration :: from_secs ( 60 ) ;
28+ pub const PING_INTERVAL : Duration = Duration :: from_secs ( 30 ) ;
2829
2930/// Open or begin a connection to an inbound or outbound peer.
3031pub trait ConnectionExt : Send + Sync {
@@ -33,6 +34,7 @@ pub trait ConnectionExt: Send + Sync {
3334 fn handshake (
3435 self ,
3536 tcp_stream : TcpStream ,
37+ timeout_params : TimeoutParams ,
3638 ) -> Result < ( ConnectionWriter , ConnectionReader , ConnectionMetrics ) , Error > ;
3739
3840 /// Listen for inbound connections on the specified socket address.
@@ -59,7 +61,7 @@ impl ConnectionExt for ConnectionConfig {
5961 let tcp_stream = TcpStream :: connect ( to. into ( ) ) ?;
6062 tcp_stream. set_read_timeout ( timeout_params. read ) ?;
6163 tcp_stream. set_write_timeout ( timeout_params. write ) ?;
62- Self :: handshake ( self , tcp_stream)
64+ Self :: handshake ( self , tcp_stream, timeout_params )
6365 }
6466
6567 fn listen (
@@ -71,12 +73,13 @@ impl ConnectionExt for ConnectionConfig {
7173 let ( tcp_stream, _) = listener. accept ( ) ?;
7274 tcp_stream. set_read_timeout ( timeout_params. read ) ?;
7375 tcp_stream. set_write_timeout ( timeout_params. write ) ?;
74- Self :: handshake ( self , tcp_stream)
76+ Self :: handshake ( self , tcp_stream, timeout_params )
7577 }
7678
7779 fn handshake (
7880 self ,
7981 mut tcp_stream : TcpStream ,
82+ timeout_params : TimeoutParams ,
8083 ) -> Result < ( ConnectionWriter , ConnectionReader , ConnectionMetrics ) , Error > {
8184 let system_time = SystemTime :: now ( ) ;
8285 let unix_time = system_time
@@ -102,6 +105,9 @@ impl ConnectionExt for ConnectionConfig {
102105 write_half. write_message ( response, & mut tcp_stream) ?;
103106 }
104107 let timed_messages = Arc :: new ( Mutex :: new ( TimedMessages :: new ( ) ) ) ;
108+ let outbound_ping = Arc :: new ( Mutex :: new ( OutboundPing :: LastReceived {
109+ then : Instant :: now ( ) ,
110+ } ) ) ;
105111 let CompletedHandshake {
106112 feeler,
107113 their_preferences,
@@ -111,13 +117,16 @@ impl ConnectionExt for ConnectionConfig {
111117 their_preferences : Arc :: clone ( & their_preferences) ,
112118 timed_messages : Arc :: clone ( & timed_messages) ,
113119 start_time : Instant :: now ( ) ,
120+ outbound_ping_state : Arc :: clone ( & outbound_ping) ,
114121 } ;
115122 let ( tx, rx) = mpsc:: channel ( ) ;
116123 let tcp_stream_clone = tcp_stream. try_clone ( ) ?;
117124 let open_writer = OpenWriter {
118125 tcp_stream : tcp_stream_clone,
119126 transport : write_half,
120127 receiver : rx,
128+ outbound_ping_state : Arc :: clone ( & outbound_ping) ,
129+ ping_interval : timeout_params. ping_interval ,
121130 } ;
122131 let write_handle =
123132 std:: thread:: spawn ( move || open_writer. maintain_connection ( ) ) ;
@@ -130,6 +139,7 @@ impl ConnectionExt for ConnectionConfig {
130139 transport : read_half,
131140 their_preferences,
132141 timed_messages,
142+ outbound_ping_state : Arc :: clone ( & outbound_ping) ,
133143 } ;
134144 return Ok ( ( writer, reader, live_connection) ) ;
135145 }
@@ -144,6 +154,7 @@ impl ConnectionExt for ConnectionConfig {
144154pub struct TimeoutParams {
145155 read : Option < Duration > ,
146156 write : Option < Duration > ,
157+ ping_interval : Duration ,
147158}
148159
149160impl TimeoutParams {
@@ -158,13 +169,18 @@ impl TimeoutParams {
158169 pub fn write_timeout ( & mut self , timeout : Duration ) {
159170 self . write = Some ( timeout)
160171 }
172+
173+ pub fn ping_interval ( & mut self , every : Duration ) {
174+ self . ping_interval = every
175+ }
161176}
162177
163178impl Default for TimeoutParams {
164179 fn default ( ) -> Self {
165180 Self {
166181 read : Some ( READ_TIMEOUT ) ,
167182 write : None ,
183+ ping_interval : PING_INTERVAL ,
168184 }
169185 }
170186}
@@ -199,6 +215,8 @@ struct OpenWriter {
199215 tcp_stream : TcpStream ,
200216 transport : WriteTransport ,
201217 receiver : mpsc:: Receiver < NetworkMessage > ,
218+ outbound_ping_state : Arc < Mutex < OutboundPing > > ,
219+ ping_interval : Duration ,
202220}
203221
204222impl OpenWriter {
@@ -215,7 +233,24 @@ impl OpenWriter {
215233 _ => return Ok ( ( ) ) ,
216234 } ,
217235 }
218- // Do traffic shaping or send ping
236+ if let Ok ( mut ping) = self . outbound_ping_state . lock ( ) {
237+ match * ping {
238+ OutboundPing :: LastReceived { then } => {
239+ if then. elapsed ( ) > self . ping_interval {
240+ let nonce: u64 = random ( ) ;
241+ self . transport
242+ . write_message ( NetworkMessage :: Ping ( nonce) , & mut self . tcp_stream ) ?;
243+
244+ * ping = OutboundPing :: Waiting {
245+ nonce,
246+ then : Instant :: now ( ) ,
247+ }
248+ }
249+ }
250+ OutboundPing :: Waiting { nonce : _, then : _ } => continue ,
251+ }
252+ }
253+ // Do traffic shaping or gossip addrs
219254 }
220255 }
221256}
@@ -227,6 +262,7 @@ pub struct ConnectionReader {
227262 transport : ReadTransport ,
228263 their_preferences : Arc < Preferences > ,
229264 timed_messages : Arc < Mutex < TimedMessages > > ,
265+ outbound_ping_state : Arc < Mutex < OutboundPing > > ,
230266}
231267
232268impl ConnectionReader {
@@ -264,6 +300,19 @@ impl ConnectionReader {
264300 lock. add_many ( TimedMessage :: Addr , list. 0 . len ( ) , Instant :: now ( ) ) ;
265301 }
266302 }
303+ NetworkMessage :: Pong ( pong) => {
304+ // There are bigger problems with this connection if the lock fails, so it is
305+ // okay to ignore the nonce.
306+ if let Ok ( mut lock) = self . outbound_ping_state . lock ( ) {
307+ if let OutboundPing :: Waiting { nonce, then : _ } = * lock {
308+ if * pong == nonce {
309+ * lock = OutboundPing :: LastReceived {
310+ then : Instant :: now ( ) ,
311+ } ;
312+ }
313+ }
314+ }
315+ }
267316 _ => ( ) ,
268317 }
269318 }
0 commit comments