@@ -96,6 +96,11 @@ defmodule ExWebRTC.DTLSTransport do
96
96
GenServer . cast ( dtls_transport , { :send_data , data } )
97
97
end
98
98
99
+ @ spec set_packet_loss ( dtls_transport ( ) , 0 .. 100 ) :: :ok
100
+ def set_packet_loss ( dtls_transport , packet_loss ) do
101
+ GenServer . cast ( dtls_transport , { :set_packet_loss , packet_loss } )
102
+ end
103
+
99
104
@ spec stop ( dtls_transport ( ) ) :: :ok
100
105
def stop ( dtls_transport ) do
101
106
GenServer . stop ( dtls_transport )
@@ -127,7 +132,8 @@ defmodule ExWebRTC.DTLSTransport do
127
132
peer_fingerprint: nil ,
128
133
dtls_state: :new ,
129
134
dtls: nil ,
130
- mode: nil
135
+ mode: nil ,
136
+ packet_loss: 0
131
137
}
132
138
133
139
notify ( state . owner , { :state_change , :new } )
@@ -142,7 +148,7 @@ defmodule ExWebRTC.DTLSTransport do
142
148
if state . mode == :active do
143
149
{ packets , timeout } = ExDTLS . do_handshake ( state . dtls )
144
150
Process . send_after ( self ( ) , :dtls_timeout , timeout )
145
- :ok = state . ice_transport . send_data ( state . ice_pid , packets )
151
+ :ok = do_send ( state , packets )
146
152
state = update_dtls_state ( state , :connecting )
147
153
Logger . debug ( "Started DTLS handshake" )
148
154
{ :reply , :ok , state }
@@ -157,7 +163,7 @@ defmodule ExWebRTC.DTLSTransport do
157
163
158
164
if state . buffered_local_packets do
159
165
Logger . debug ( "Sending buffered DTLS packets" )
160
- :ok = state . ice_transport . send_data ( state . ice_pid , state . buffered_local_packets )
166
+ :ok = do_send ( state , state . buffered_local_packets )
161
167
state = % { state | buffered_local_packets: nil }
162
168
{ :reply , :ok , state }
163
169
else
@@ -236,7 +242,7 @@ defmodule ExWebRTC.DTLSTransport do
236
242
@ impl true
237
243
def handle_cast ( { :send_rtp , data } , % { dtls_state: :connected , ice_connected: true } = state ) do
238
244
case ExLibSRTP . protect ( state . out_srtp , data ) do
239
- { :ok , protected } -> state . ice_transport . send_data ( state . ice_pid , protected )
245
+ { :ok , protected } -> do_send ( state , protected )
240
246
{ :error , reason } -> Logger . warning ( "Unable to protect RTP: #{ inspect ( reason ) } " )
241
247
end
242
248
@@ -252,7 +258,7 @@ defmodule ExWebRTC.DTLSTransport do
252
258
@ impl true
253
259
def handle_cast ( { :send_rtcp , data } , state ) do
254
260
case ExLibSRTP . protect_rtcp ( state . out_srtp , data ) do
255
- { :ok , protected } -> state . ice_transport . send_data ( state . ice_pid , protected )
261
+ { :ok , protected } -> do_send ( state , protected )
256
262
{ :error , reason } -> Logger . warning ( "Unable to protect RTCP: #{ inspect ( reason ) } " )
257
263
end
258
264
@@ -262,18 +268,24 @@ defmodule ExWebRTC.DTLSTransport do
262
268
@ impl true
263
269
def handle_cast ( { :send_data , data } , state ) do
264
270
case ExDTLS . write_data ( state . dtls , data ) do
265
- { :ok , protected } -> state . ice_transport . send_data ( state . ice_pid , protected )
271
+ { :ok , protected } -> do_send ( state , protected )
266
272
{ :error , reason } -> Logger . warning ( "Unable to protect data: #{ inspect ( reason ) } " )
267
273
end
268
274
269
275
{ :noreply , state }
270
276
end
271
277
278
+ @ impl true
279
+ def handle_cast ( { :set_packet_loss , value } , state ) do
280
+ state = % { state | packet_loss: value }
281
+ { :noreply , state }
282
+ end
283
+
272
284
@ impl true
273
285
def handle_info ( :dtls_timeout , % { buffered_local_packets: buffered_local_packets } = state ) do
274
286
case ExDTLS . handle_timeout ( state . dtls ) do
275
287
{ :retransmit , packets , timeout } when state . ice_connected ->
276
- state . ice_transport . send_data ( state . ice_pid , packets )
288
+ do_send ( state , packets )
277
289
Logger . debug ( "Retransmitted DTLS packets" )
278
290
Process . send_after ( self ( ) , :dtls_timeout , timeout )
279
291
@@ -327,7 +339,7 @@ defmodule ExWebRTC.DTLSTransport do
327
339
defp handle_ice_data ( { :data , << f , _rest :: binary >> = data } , state ) when f in 20 .. 63 do
328
340
case ExDTLS . handle_data ( state . dtls , data ) do
329
341
{ :handshake_packets , packets , timeout } when state . ice_connected ->
330
- :ok = state . ice_transport . send_data ( state . ice_pid , packets )
342
+ :ok = do_send ( state , packets )
331
343
Process . send_after ( self ( ) , :dtls_timeout , timeout )
332
344
state = update_dtls_state ( state , :connecting )
333
345
{ :ok , state }
@@ -346,7 +358,7 @@ defmodule ExWebRTC.DTLSTransport do
346
358
{ :handshake_finished , lkm , rkm , profile , packets } ->
347
359
Logger . debug ( "DTLS handshake finished" )
348
360
state = update_remote_cert_info ( state )
349
- state . ice_transport . send_data ( state . ice_pid , packets )
361
+ do_send ( state , packets )
350
362
351
363
peer_fingerprint =
352
364
state . dtls
@@ -466,5 +478,16 @@ defmodule ExWebRTC.DTLSTransport do
466
478
% { state | buffered_remote_rtp_packets: [ ] }
467
479
end
468
480
481
+ defp do_send ( % { packet_loss: 0 } = state , data ) ,
482
+ do: state . ice_transport . send_data ( state . ice_pid , data )
483
+
484
+ defp do_send ( state , data ) do
485
+ if Enum . random ( 1 .. 100 ) > state . packet_loss do
486
+ state . ice_transport . send_data ( state . ice_pid , data )
487
+ else
488
+ :ok
489
+ end
490
+ end
491
+
469
492
defp notify ( dst , msg ) , do: send ( dst , { :dtls_transport , self ( ) , msg } )
470
493
end
0 commit comments