@@ -17,12 +17,14 @@ use std::collections::HashMap;
17
17
use std:: future:: Future ;
18
18
use std:: pin:: Pin ;
19
19
use std:: sync:: Arc ;
20
+ use std:: time:: Duration ;
20
21
use tokio:: sync:: Mutex ;
21
22
22
23
/// GeneratorBuilder can be used to configure Responder Interceptor
23
24
#[ derive( Default ) ]
24
25
pub struct ResponderBuilder {
25
26
log2_size : Option < u8 > ,
27
+ max_packet_age : Option < Duration > ,
26
28
}
27
29
28
30
impl ResponderBuilder {
@@ -32,6 +34,15 @@ impl ResponderBuilder {
32
34
self . log2_size = Some ( log2_size) ;
33
35
self
34
36
}
37
+
38
+ /// with_max_packet_age sets the max age of packets that will be resent.
39
+ ///
40
+ /// When a resend is requested, packets that were first sent more than `max_packet_age` ago
41
+ /// will not be resent.
42
+ pub fn with_max_packet_age ( mut self , max_packet_age : Duration ) -> ResponderBuilder {
43
+ self . max_packet_age = Some ( max_packet_age) ;
44
+ self
45
+ }
35
46
}
36
47
37
48
impl InterceptorBuilder for ResponderBuilder {
@@ -43,6 +54,7 @@ impl InterceptorBuilder for ResponderBuilder {
43
54
} else {
44
55
13 // 8192 = 1 << 13
45
56
} ,
57
+ max_packet_age : self . max_packet_age ,
46
58
streams : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
47
59
} ) ,
48
60
} ) )
@@ -51,13 +63,15 @@ impl InterceptorBuilder for ResponderBuilder {
51
63
52
64
pub struct ResponderInternal {
53
65
log2_size : u8 ,
66
+ max_packet_age : Option < Duration > ,
54
67
streams : Arc < Mutex < HashMap < u32 , Arc < ResponderStream > > > > ,
55
68
}
56
69
57
70
impl ResponderInternal {
58
71
async fn resend_packets (
59
72
streams : Arc < Mutex < HashMap < u32 , Arc < ResponderStream > > > > ,
60
73
nack : TransportLayerNack ,
74
+ max_packet_age : Option < Duration > ,
61
75
) {
62
76
let stream = {
63
77
let m = streams. lock ( ) . await ;
@@ -73,10 +87,19 @@ impl ResponderInternal {
73
87
n. range ( Box :: new (
74
88
move |seq : u16 | -> Pin < Box < dyn Future < Output = bool > + Send + ' static > > {
75
89
let stream3 = Arc :: clone ( & stream2) ;
90
+
76
91
Box :: pin ( async move {
77
92
if let Some ( p) = stream3. get ( seq) . await {
93
+ let should_send = max_packet_age
94
+ . map ( |max_age| p. age ( ) < max_age)
95
+ . unwrap_or ( true ) ;
96
+
97
+ if !should_send {
98
+ return true ;
99
+ }
100
+
78
101
let a = Attributes :: new ( ) ;
79
- if let Err ( err) = stream3. next_rtp_writer . write ( & p, & a) . await {
102
+ if let Err ( err) = stream3. next_rtp_writer . write ( & p. packet , & a) . await {
80
103
log:: warn!( "failed resending nacked packet: {}" , err) ;
81
104
}
82
105
}
@@ -92,6 +115,7 @@ impl ResponderInternal {
92
115
93
116
pub struct ResponderRtcpReader {
94
117
parent_rtcp_reader : Arc < dyn RTCPReader + Send + Sync > ,
118
+ max_packet_age : Option < Duration > ,
95
119
internal : Arc < ResponderInternal > ,
96
120
}
97
121
@@ -106,8 +130,9 @@ impl RTCPReader for ResponderRtcpReader {
106
130
if let Some ( nack) = p. as_any ( ) . downcast_ref :: < TransportLayerNack > ( ) {
107
131
let nack = nack. clone ( ) ;
108
132
let streams = Arc :: clone ( & self . internal . streams ) ;
133
+ let max_packet_age = self . max_packet_age ;
109
134
tokio:: spawn ( async move {
110
- ResponderInternal :: resend_packets ( streams, nack) . await ;
135
+ ResponderInternal :: resend_packets ( streams, nack, max_packet_age ) . await ;
111
136
} ) ;
112
137
}
113
138
}
@@ -138,6 +163,7 @@ impl Interceptor for Responder {
138
163
) -> Arc < dyn RTCPReader + Send + Sync > {
139
164
Arc :: new ( ResponderRtcpReader {
140
165
internal : Arc :: clone ( & self . internal ) ,
166
+ max_packet_age : self . internal . max_packet_age ,
141
167
parent_rtcp_reader : reader,
142
168
} ) as Arc < dyn RTCPReader + Send + Sync >
143
169
}
0 commit comments