1
1
use std:: error:: Error as StdError ;
2
2
use std:: marker:: Unpin ;
3
+ use std:: sync:: { Arc , Mutex } ;
3
4
#[ cfg( feature = "runtime" ) ]
4
5
use std:: time:: Duration ;
5
6
@@ -24,7 +25,7 @@ use crate::service::HttpService;
24
25
25
26
use crate :: upgrade:: { OnUpgrade , Pending , Upgraded } ;
26
27
use crate :: { Body , Response } ;
27
-
28
+ use tokio :: time :: Sleep ;
28
29
// Our defaults are chosen for the "majority" case, which usually are not
29
30
// resource constrained, and so the spec default of 64kb can be too limiting
30
31
// for performance.
@@ -36,6 +37,9 @@ const DEFAULT_STREAM_WINDOW: u32 = 1024 * 1024; // 1mb
36
37
const DEFAULT_MAX_FRAME_SIZE : u32 = 1024 * 16 ; // 16kb
37
38
const DEFAULT_MAX_SEND_BUF_SIZE : usize = 1024 * 400 ; // 400kb
38
39
40
+ // TODO will be replace by config in the formal pull request
41
+ const DEFAULT_CONN_IDLE_TIMEOUT : Duration = Duration :: from_secs ( 65 ) ;
42
+
39
43
#[ derive( Clone , Debug ) ]
40
44
pub ( crate ) struct Config {
41
45
pub ( crate ) adaptive_window : bool ,
@@ -100,6 +104,7 @@ where
100
104
ping : Option < ( ping:: Recorder , ping:: Ponger ) > ,
101
105
conn : Connection < T , SendBuf < B :: Data > > ,
102
106
closing : Option < crate :: Error > ,
107
+ conn_idle_timeout : Arc < Mutex < Pin < Box < Sleep > > > >
103
108
}
104
109
105
110
impl < T , S , B , E > Server < T , S , B , E >
@@ -202,6 +207,7 @@ where
202
207
ping,
203
208
conn,
204
209
closing : None ,
210
+ conn_idle_timeout : Arc :: new ( Mutex :: new ( Box :: pin ( tokio:: time:: sleep ( DEFAULT_CONN_IDLE_TIMEOUT ) ) ) )
205
211
} )
206
212
}
207
213
State :: Serving ( ref mut srv) => {
@@ -224,6 +230,17 @@ where
224
230
T : AsyncRead + AsyncWrite + Unpin ,
225
231
B : HttpBody + ' static ,
226
232
{
233
+
234
+ fn reset_conn_idle_timeout ( & self , time : Duration ) {
235
+ let mut sleep = self . conn_idle_timeout . lock ( ) . unwrap ( ) ;
236
+ sleep. as_mut ( ) . reset ( tokio:: time:: Instant :: now ( ) + time) ;
237
+ }
238
+
239
+ fn poll_conn_idle_timeout ( & self , cx : & mut task:: Context < ' _ > ) -> bool {
240
+ let mut sleep = self . conn_idle_timeout . lock ( ) . unwrap ( ) ;
241
+ sleep. as_mut ( ) . poll ( cx) . is_ready ( )
242
+ }
243
+
227
244
fn poll_server < S , E > (
228
245
& mut self ,
229
246
cx : & mut task:: Context < ' _ > ,
@@ -269,10 +286,16 @@ where
269
286
break ;
270
287
}
271
288
}
272
-
289
+ if self . poll_conn_idle_timeout ( cx) {
290
+ self . conn . graceful_shutdown ( ) ;
291
+ trace ! ( "conn is close with idle" ) ;
292
+ return Poll :: Ready ( Ok ( ( ) ) ) ;
293
+ }
273
294
// When the service is ready, accepts an incoming request.
274
295
match ready ! ( self . conn. poll_accept( cx) ) {
275
296
Some ( Ok ( ( req, mut respond) ) ) => {
297
+ // Avoid request failures due to timeout.
298
+ self . reset_conn_idle_timeout ( Duration :: from_secs ( 60 * 60 * 24 ) ) ;
276
299
trace ! ( "incoming request" ) ;
277
300
let content_length = headers:: content_length_parse_all ( req. headers ( ) ) ;
278
301
let ping = self
@@ -317,7 +340,7 @@ where
317
340
req. extensions_mut ( ) . insert ( Protocol :: from_inner ( protocol) ) ;
318
341
}
319
342
320
- let fut = H2Stream :: new ( service. call ( req) , connect_parts, respond) ;
343
+ let fut = H2Stream :: new ( service. call ( req) , connect_parts, respond, self . conn_idle_timeout . clone ( ) ) ;
321
344
exec. execute_h2stream ( fut) ;
322
345
}
323
346
Some ( Err ( e) ) => {
@@ -373,6 +396,7 @@ pin_project! {
373
396
reply: SendResponse <SendBuf <B :: Data >>,
374
397
#[ pin]
375
398
state: H2StreamState <F , B >,
399
+ conn_idle_timeout: Arc <Mutex <Pin <Box <Sleep >>>>,
376
400
}
377
401
}
378
402
@@ -408,10 +432,12 @@ where
408
432
fut : F ,
409
433
connect_parts : Option < ConnectParts > ,
410
434
respond : SendResponse < SendBuf < B :: Data > > ,
435
+ conn_idle_timeout : Arc < Mutex < Pin < Box < Sleep > > > >
411
436
) -> H2Stream < F , B > {
412
437
H2Stream {
413
438
reply : respond,
414
439
state : H2StreamState :: Service { fut, connect_parts } ,
440
+ conn_idle_timeout,
415
441
}
416
442
}
417
443
}
@@ -534,7 +560,11 @@ where
534
560
type Output = ( ) ;
535
561
536
562
fn poll ( self : Pin < & mut Self > , cx : & mut task:: Context < ' _ > ) -> Poll < Self :: Output > {
537
- self . poll2 ( cx) . map ( |res| {
563
+ let conn_idle_timeout = self . conn_idle_timeout . clone ( ) ;
564
+ let poll = self . poll2 ( cx) ;
565
+ poll. map ( |res| {
566
+ let mut sleep = conn_idle_timeout. lock ( ) . unwrap ( ) ;
567
+ sleep. as_mut ( ) . reset ( tokio:: time:: Instant :: now ( ) + DEFAULT_CONN_IDLE_TIMEOUT ) ;
538
568
if let Err ( e) = res {
539
569
debug ! ( "stream error: {}" , e) ;
540
570
}
0 commit comments