@@ -63,7 +63,7 @@ defmodule ExWebRTC.PeerConnection do
6363
6464 For the exact meaning, refer to the [RTCDtlsTransport: state property](https://developer.mozilla.org/en-US/docs/Web/API/RTCDtlsTransport/state)
6565 """
66- @ type dtls_transport_state ( ) :: :new | :connecting | :connected | :failed
66+ @ type dtls_transport_state ( ) :: :new | :connecting | :connected | :closed | : failed
6767
6868 @ typedoc """
6969 Possible signaling states.
@@ -105,8 +105,8 @@ defmodule ExWebRTC.PeerConnection do
105105 | { :track_muted , MediaStreamTrack . id ( ) }
106106 | { :track_ended , MediaStreamTrack . id ( ) }
107107 | { :data , DataChannel . ref ( ) , binary ( ) }
108- | { :rtp , MediaStreamTrack . id ( ) , String . t ( ) | nil , ExRTP.Packet . t ( ) } }
109- | { :rtcp , [ { MediaStreamTrack . id ( ) | nil , ExRTCP.Packet . packet ( ) } ] }
108+ | { :rtp , MediaStreamTrack . id ( ) , String . t ( ) | nil , ExRTP.Packet . t ( ) }
109+ | { :rtcp , [ { MediaStreamTrack . id ( ) | nil , ExRTCP.Packet . packet ( ) } ] } }
110110
111111 #### NON-MDN-API ####
112112
@@ -472,7 +472,7 @@ defmodule ExWebRTC.PeerConnection do
472472 peer_connection ( ) ,
473473 RTPTransceiver . kind ( ) | MediaStreamTrack . t ( ) ,
474474 direction: RTPTransceiver . direction ( )
475- ) :: { :ok , RTPTransceiver . t ( ) }
475+ ) :: { :ok , RTPTransceiver . t ( ) } | { :error , term ( ) }
476476 def add_transceiver ( peer_connection , kind_or_track , options \\ [ ] ) do
477477 GenServer . call ( peer_connection , { :add_transceiver , kind_or_track , options } )
478478 end
@@ -507,7 +507,8 @@ defmodule ExWebRTC.PeerConnection do
507507
508508 For more information, refer to the [RTCPeerConnection: addTrack() method](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack).
509509 """
510- @ spec add_track ( peer_connection ( ) , MediaStreamTrack . t ( ) ) :: { :ok , RTPSender . t ( ) }
510+ @ spec add_track ( peer_connection ( ) , MediaStreamTrack . t ( ) ) ::
511+ { :ok , RTPSender . t ( ) } | { :error , term ( ) }
511512 def add_track ( peer_connection , track ) do
512513 GenServer . call ( peer_connection , { :add_track , track } )
513514 end
@@ -574,11 +575,20 @@ defmodule ExWebRTC.PeerConnection do
574575 @ doc """
575576 Closes the PeerConnection.
576577
577- This function kills the `peer_connection` process.
578+ This function doest not kill the `peer_connection` process.
579+ If you want to stop the `peer_connection` process, see `stop/1`.
578580 For more information, refer to the [RTCPeerConnection: close() method](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/close).
579581 """
580582 @ spec close ( peer_connection ( ) ) :: :ok
581583 def close ( peer_connection ) do
584+ GenServer . call ( peer_connection , :close )
585+ end
586+
587+ @ doc """
588+ Closes and stops PeerConnection process.
589+ """
590+ @ spec stop ( peer_connection ( ) ) :: :ok
591+ def stop ( peer_connection ) do
582592 GenServer . stop ( peer_connection )
583593 end
584594
@@ -1067,6 +1077,14 @@ defmodule ExWebRTC.PeerConnection do
10671077
10681078 if Code . ensure_loaded? ( ExSCTP ) do
10691079 @ impl true
1080+ def handle_call (
1081+ { :create_data_channel , _label , _opts } ,
1082+ _from ,
1083+ % { connection_state: :closed } = state
1084+ ) do
1085+ { :reply , { :error , :closed } , state }
1086+ end
1087+
10701088 def handle_call ( { :create_data_channel , label , opts } , _from , state ) do
10711089 ordered = Keyword . get ( opts , :ordered , true )
10721090 lifetime = Keyword . get ( opts , :max_packet_life_time )
@@ -1075,7 +1093,7 @@ defmodule ExWebRTC.PeerConnection do
10751093
10761094 with true <- byte_size ( label ) < 65_535 ,
10771095 true <- lifetime == nil or max_rtx == nil do
1078- { events , channel , sctp_transport } =
1096+ { :ok , events , channel , sctp_transport } =
10791097 SCTPTransport . add_channel (
10801098 state . sctp_transport ,
10811099 label ,
@@ -1271,9 +1289,17 @@ defmodule ExWebRTC.PeerConnection do
12711289 { :reply , stats , state }
12721290 end
12731291
1292+ @ impl true
1293+ def handle_call ( :close , _from , state ) do
1294+ Logger . debug ( "Closing peer connection" )
1295+ # don't emit state change events
1296+ state = do_close ( state , notify: false )
1297+ { :reply , :ok , state }
1298+ end
1299+
12741300 @ impl true
12751301 def handle_cast ( { :send_rtp , track_id , packet , opts } , % { conn_state: conn_state } = state )
1276- when conn_state != :failed do
1302+ when conn_state not in [ :failed , :closed ] do
12771303 rtx? = Keyword . get ( opts , :rtx? , false )
12781304
12791305 # TODO: iterating over transceivers is not optimal
@@ -1331,7 +1357,7 @@ defmodule ExWebRTC.PeerConnection do
13311357
13321358 @ impl true
13331359 def handle_cast ( { :send_pli , track_id , rid } , % { conn_state: conn_state } = state )
1334- when conn_state != :failed do
1360+ when conn_state not in [ :failed , :closed ] do
13351361 state . transceivers
13361362 |> Enum . with_index ( )
13371363 |> Enum . find ( fn { tr , _idx } -> tr . receiver . track . id == track_id end )
@@ -1365,7 +1391,7 @@ defmodule ExWebRTC.PeerConnection do
13651391 if Code . ensure_loaded? ( ExSCTP ) do
13661392 @ impl true
13671393 def handle_cast ( { :send_data , channel_ref , data_type , data } , % { conn_state: conn_state } = state )
1368- when conn_state != :failed do
1394+ when conn_state not in [ :failed , :closed ] do
13691395 { events , sctp_transport } =
13701396 SCTPTransport . send ( state . sctp_transport , channel_ref , data_type , data )
13711397
@@ -1432,12 +1458,17 @@ defmodule ExWebRTC.PeerConnection do
14321458
14331459 next_conn_state = next_conn_state ( state . ice_state , new_dtls_state )
14341460
1435- state =
1436- % { state | dtls_state: new_dtls_state }
1437- |> update_conn_state ( next_conn_state )
1438- |> maybe_connect_sctp ( )
1461+ if next_conn_state == :closed and state . conn_state != :closed do
1462+ state = do_close ( state )
1463+ { :noreply , state }
1464+ else
1465+ state =
1466+ % { state | dtls_state: new_dtls_state }
1467+ |> update_conn_state ( next_conn_state )
1468+ |> maybe_connect_sctp ( )
14391469
1440- { :noreply , state }
1470+ { :noreply , state }
1471+ end
14411472 end
14421473
14431474 @ impl true
@@ -1955,15 +1986,24 @@ defmodule ExWebRTC.PeerConnection do
19551986 defp next_signaling_state ( :have_remote_pranswer , :remote , :answer ) , do: { :ok , :stable }
19561987 defp next_signaling_state ( :have_remote_pranswer , _ , _ ) , do: { :error , :invalid_state }
19571988
1958- defp update_signaling_state ( % { signaling_state: signaling_state } = state , signaling_state ) ,
1959- do: state
1989+ defp update_signaling_state ( state , signaling_state , opts \\ [ ] )
1990+
1991+ defp update_signaling_state (
1992+ % { signaling_state: signaling_state } = state ,
1993+ signaling_state ,
1994+ _opts
1995+ ) ,
1996+ do: state
19601997
1961- defp update_signaling_state ( state , new_signaling_state ) do
1998+ defp update_signaling_state ( state , new_signaling_state , opts ) do
19621999 Logger . debug (
19632000 "Changing PeerConnection signaling state state: #{ state . signaling_state } -> #{ new_signaling_state } "
19642001 )
19652002
1966- notify ( state . owner , { :signaling_state_change , new_signaling_state } )
2003+ if opts [ :notify ] != false do
2004+ notify ( state . owner , { :signaling_state_change , new_signaling_state } )
2005+ end
2006+
19672007 % { state | signaling_state: new_signaling_state }
19682008 end
19692009
@@ -2192,12 +2232,15 @@ defmodule ExWebRTC.PeerConnection do
21922232 defp get_last_answer ( % { current_remote_desc: { :answer , desc } } ) , do: desc
21932233
21942234 # TODO support :disconnected state - our ICE doesn't provide disconnected state for now
2195- # TODO support :closed state
21962235 # the order of these clauses is important
21972236 defp next_conn_state ( ice_state , dtls_state )
21982237
2199- defp next_conn_state ( ice_state , dtls_state ) when ice_state == :failed or dtls_state == :failed ,
2200- do: :failed
2238+ # Give closed precedence over failed.
2239+ # Failed connection can be restarted.
2240+ # Closed connection can't be reused.
2241+ defp next_conn_state ( :closed , _dtls_state ) , do: :closed
2242+
2243+ defp next_conn_state ( _ice_state , :closed ) , do: :closed
22012244
22022245 defp next_conn_state ( :failed , _dtls_state ) , do: :failed
22032246
@@ -2212,11 +2255,16 @@ defmodule ExWebRTC.PeerConnection do
22122255 defp next_conn_state ( ice_state , :connected ) when ice_state in [ :connected , :completed ] ,
22132256 do: :connected
22142257
2215- defp update_conn_state ( % { conn_state: conn_state } = state , conn_state ) , do: state
2258+ defp update_conn_state ( state , conn_state , opts \\ [ ] )
2259+ defp update_conn_state ( % { conn_state: conn_state } = state , conn_state , _opts ) , do: state
22162260
2217- defp update_conn_state ( state , new_conn_state ) do
2261+ defp update_conn_state ( state , new_conn_state , opts ) do
22182262 Logger . debug ( "Changing PeerConnection state: #{ state . conn_state } -> #{ new_conn_state } " )
2219- notify ( state . owner , { :connection_state_change , new_conn_state } )
2263+
2264+ if opts [ :notify ] != false do
2265+ notify ( state . owner , { :connection_state_change , new_conn_state } )
2266+ end
2267+
22202268 % { state | conn_state: new_conn_state }
22212269 end
22222270
@@ -2413,6 +2461,23 @@ defmodule ExWebRTC.PeerConnection do
24132461 % SessionDescription { type: type , sdp: to_string ( sdp ) }
24142462 end
24152463
2464+ defp do_close ( state , opts \\ [ ] ) do
2465+ transceivers = Enum . map ( state . transceivers , & RTPTransceiver . stop ( & 1 ) )
2466+ sctp_transport = SCTPTransport . close_abruptly ( state . sctp_transport )
2467+ :ok = DTLSTransport . close ( state . dtls_transport )
2468+ :ok = state . ice_transport . close ( state . ice_pid )
2469+
2470+ % {
2471+ state
2472+ | ice_state: :closed ,
2473+ dtls_state: :closed ,
2474+ transceivers: transceivers ,
2475+ sctp_transport: sctp_transport
2476+ }
2477+ |> update_signaling_state ( :closed , opts )
2478+ |> update_conn_state ( :closed , opts )
2479+ end
2480+
24162481 defp generate_ssrcs ( state ) do
24172482 generate_ssrcs ( state . transceivers , Map . keys ( state . demuxer . ssrc_to_mid ) )
24182483 end
0 commit comments