@@ -131,8 +131,8 @@ defmodule ExWebRTC.DTLSTransport do
131131 remote_cert: nil ,
132132 remote_base64_cert: nil ,
133133 remote_fingerprint: nil ,
134- in_srtp: ExLibSRTP . new ( ) ,
135- out_srtp: ExLibSRTP . new ( ) ,
134+ in_srtp: nil ,
135+ out_srtp: nil ,
136136 # sha256 hex dump
137137 peer_fingerprint: nil ,
138138 dtls_state: :new ,
@@ -217,9 +217,18 @@ defmodule ExWebRTC.DTLSTransport do
217217 end
218218
219219 @ impl true
220- def handle_call ( { :start_dtls , mode , peer_fingerprint } , _from , % { dtls: nil } = state )
221- when mode in [ :active , :passive ] do
222- Logger . debug ( "Started DTLSTransport with role #{ mode } " )
220+ def handle_call (
221+ { :start_dtls , mode , peer_fingerprint } ,
222+ _from ,
223+ % { dtls: dtls , dtls_state: dtls_state } = state
224+ )
225+ when mode in [ :active , :passive ] and ( dtls == nil or dtls_state == :closed ) do
226+ if dtls_state == :closed do
227+ Logger . debug ( "Re-initializing DTLSTransport with role #{ mode } " )
228+ else
229+ Logger . debug ( "Starting DTLSTransport with role #{ mode } " )
230+ end
231+
223232 ex_dtls_mode = if mode == :active , do: :client , else: :server
224233
225234 dtls =
@@ -234,16 +243,26 @@ defmodule ExWebRTC.DTLSTransport do
234243 # plant the buffered remote packets in the mailbox
235244 # as if it came from the ICE transport
236245 case state . buffered_remote_packets do
237- nil -> :ok
238- data -> send ( self ( ) , { :ex_ice , state . ice_pid , { :data , data } } )
246+ nil ->
247+ :ok
248+
249+ data ->
250+ dbg ( :sending )
251+ send ( self ( ) , { :ex_ice , state . ice_pid , { :data , data } } )
239252 end
240253
241254 state = % {
242255 state
243256 | dtls: dtls ,
257+ dtls_state: :new ,
244258 mode: mode ,
259+ in_srtp: ExLibSRTP . new ( ) ,
260+ out_srtp: ExLibSRTP . new ( ) ,
245261 peer_fingerprint: peer_fingerprint ,
246- buffered_remote_packets: nil
262+ # cleare remote info in case we are re-initializing dtls transport
263+ remote_cert: nil ,
264+ remote_base64_cert: nil ,
265+ remote_fingerprint: nil
247266 }
248267
249268 { :reply , :ok , state }
@@ -262,9 +281,7 @@ defmodule ExWebRTC.DTLSTransport do
262281
263282 @ impl true
264283 def handle_call ( :close , _from , state ) do
265- { :ok , packets } = ExDTLS . close ( state . dtls )
266- :ok = do_send ( state , packets )
267- state = update_dtls_state ( state , :closed , notify: false )
284+ state = do_close ( state , notify: false )
268285 { :reply , :ok , state }
269286 end
270287
@@ -360,8 +377,7 @@ defmodule ExWebRTC.DTLSTransport do
360377 # See W3C WebRTC sec. 5.5.1
361378 # peer_closed_for_writing is returned when the remote side
362379 # sends close_notify alert
363- ExDTLS . close ( state . dtls )
364- state = update_dtls_state ( state , :closed )
380+ state = do_close ( state )
365381 { :noreply , state }
366382
367383 { :error , _reason } ->
@@ -382,9 +398,20 @@ defmodule ExWebRTC.DTLSTransport do
382398 Logger . debug ( "Stopping DTLSTransport with reason: #{ inspect ( reason ) } " )
383399 end
384400
385- defp handle_ice_data ( { :data , _data } , % { dtls_state: dtls_state } = state )
386- when dtls_state in [ :failed , :closed ] do
387- Logger . debug ( "Received DTLS packets in state #{ dtls_state } . Ignoring." )
401+ defp handle_ice_data ( { :data , _data } , % { dtls_state: :closed } = state ) do
402+ # Ignore incoming packets when we are in the closed state.
403+ # IMPORTNAT!!!
404+ # This isn't optimal.
405+ # When DTLSTransport has been closed because of receiving close_notify alert,
406+ # it can still be re-used after doing an ice restart with a different peer.
407+ # In such case, we might start getting remote ICE packets before getting remote SDP answer
408+ # (see the case clause below).
409+ # These packets could be buffered and processed once we receive said SDP answer to speedup
410+ # connection establishment time (instead of waiting for retransmissions).
411+ # However, it is hard to differentiate this case from a case where DTLSTransport received
412+ # close_notify alert, but the remote side behaves incorrectly and still sends ICE packets.
413+ # Buffering incoming packets in closed state, we don't know whether they belong to current or previous
414+ # session, which can lead to hard to find bugs.
388415 { :ok , state }
389416 end
390417
@@ -542,6 +569,23 @@ defmodule ExWebRTC.DTLSTransport do
542569 % { state | buffered_remote_rtp_packets: [ ] }
543570 end
544571
572+ defp do_close ( state , opts \\ [ ] ) do
573+ { :ok , packets } = ExDTLS . close ( state . dtls )
574+ :ok = do_send ( state , packets )
575+
576+ % {
577+ state
578+ | buffered_local_packets: nil ,
579+ buffered_remote_packets: nil ,
580+ buffered_remote_rtp_packets: [ ] ,
581+ in_srtp: nil ,
582+ out_srtp: nil ,
583+ dtls: nil ,
584+ mode: nil
585+ }
586+ |> update_dtls_state ( :closed , opts )
587+ end
588+
545589 defp do_send ( state , data ) when is_list ( data ) do
546590 Enum . each ( data , & ( :ok = do_send ( state , & 1 ) ) )
547591 end
0 commit comments