@@ -66,16 +66,26 @@ defmodule ExICE.ICEAgent do
66
66
67
67
@ typedoc """
68
68
ICE Agent configuration options.
69
+ All notifications are by default sent to a process that spawns `ExICE`.
70
+ This behavior can be overwritten using the following options.
69
71
70
72
* `ip_filter` - filter applied when gathering local candidates
71
73
* `stun_servers` - list of STUN servers
74
+ * `on_gathering_state_change` - where to send gathering state change notifications. Defaults to a process that spawns `ExICE`.
75
+ * `on_connection_state_change` - where to send connection state change notifications. Defaults to a process that spawns `ExICE`.
76
+ * `on_data` - where to send data. Defaults to a process that spawns `ExICE`.
77
+ * `on_new_candidate` - where to send new candidates. Defaults to a process that spawns `ExICE`.
72
78
73
79
Currently, there is no support for local relay (TURN) candidates
74
80
however, remote relay candidates work correctly.
75
81
"""
76
82
@ type opts ( ) :: [
77
83
ip_filter: ( :inet . ip_address ( ) -> boolean ) ,
78
- stun_servers: [ String . t ( ) ]
84
+ stun_servers: [ String . t ( ) ] ,
85
+ on_gathering_state_change: pid ( ) | nil ,
86
+ on_connection_state_change: pid ( ) | nil ,
87
+ on_data: pid ( ) | nil ,
88
+ on_new_candidate: pid ( ) | nil
79
89
]
80
90
81
91
defguardp are_pairs_equal ( p1 , p2 )
@@ -99,6 +109,38 @@ defmodule ExICE.ICEAgent do
99
109
GenServer . start_link ( __MODULE__ , opts ++ [ role: role , controlling_process: self ( ) ] )
100
110
end
101
111
112
+ @ doc """
113
+ Configures where to send gathering state change notifications.
114
+ """
115
+ @ spec on_gathering_state_change ( pid ( ) , pid ( ) | nil ) :: :ok
116
+ def on_gathering_state_change ( ice_agent , send_to ) do
117
+ GenServer . call ( ice_agent , { :on_gathering_state_change , send_to } )
118
+ end
119
+
120
+ @ doc """
121
+ Configures where to send connection state change notifications.
122
+ """
123
+ @ spec on_connection_state_change ( pid ( ) , pid ( ) | nil ) :: :ok
124
+ def on_connection_state_change ( ice_agent , send_to ) do
125
+ GenServer . call ( ice_agent , { :on_connection_state_change , send_to } )
126
+ end
127
+
128
+ @ doc """
129
+ Configures where to send data.
130
+ """
131
+ @ spec on_data ( pid ( ) , pid ( ) | nil ) :: :ok
132
+ def on_data ( ice_agent , send_to ) do
133
+ GenServer . call ( ice_agent , { :on_data , send_to } )
134
+ end
135
+
136
+ @ doc """
137
+ Configures where to send new candidates.
138
+ """
139
+ @ spec on_new_candidate ( pid ( ) , pid ( ) | nil ) :: :ok
140
+ def on_new_candidate ( ice_agent , send_to ) do
141
+ GenServer . call ( ice_agent , { :on_new_candidate , send_to } )
142
+ end
143
+
102
144
@ doc """
103
145
Gets local credentials.
104
146
@@ -200,9 +242,15 @@ defmodule ExICE.ICEAgent do
200
242
201
243
{ local_ufrag , local_pwd } = generate_credentials ( )
202
244
245
+ controlling_process = Keyword . fetch! ( opts , :controlling_process )
246
+
203
247
state = % {
204
248
state: :new ,
205
- controlling_process: Keyword . fetch! ( opts , :controlling_process ) ,
249
+ controlling_process: controlling_process ,
250
+ on_connection_state_change: opts [ :on_connection_state_change ] || controlling_process ,
251
+ on_gathering_state_change: opts [ :on_gathering_state_change ] || controlling_process ,
252
+ on_data: opts [ :on_data ] || controlling_process ,
253
+ on_new_candidate: opts [ :on_new_candidate ] || controlling_process ,
206
254
ta_timer: nil ,
207
255
gathering_transactions: % { } ,
208
256
ip_filter: opts [ :ip_filter ] ,
@@ -230,6 +278,26 @@ defmodule ExICE.ICEAgent do
230
278
{ :ok , state }
231
279
end
232
280
281
+ @ impl true
282
+ def handle_call ( { :on_gathering_state_change , send_to } , _from , state ) do
283
+ { :reply , :ok , % { state | on_gathering_state_change: send_to } }
284
+ end
285
+
286
+ @ impl true
287
+ def handle_call ( { :on_connection_state_change , send_to } , _from , state ) do
288
+ { :reply , :ok , % { state | on_connection_state_change: send_to } }
289
+ end
290
+
291
+ @ impl true
292
+ def handle_call ( { :on_data , send_to } , _from , state ) do
293
+ { :reply , :ok , % { state | on_data: send_to } }
294
+ end
295
+
296
+ @ impl true
297
+ def handle_call ( { :on_new_candidate , send_to } , _from , state ) do
298
+ { :reply , :ok , % { state | on_new_candidate: send_to } }
299
+ end
300
+
233
301
@ impl true
234
302
def handle_call ( :get_local_credentials , _from , state ) do
235
303
{ :reply , { :ok , state . local_ufrag , state . local_pwd } , state }
@@ -277,16 +345,13 @@ defmodule ExICE.ICEAgent do
277
345
@ impl true
278
346
def handle_cast ( :gather_candidates , % { gathering_state: :new } = state ) do
279
347
Logger . debug ( "Gathering state change: #{ state . gathering_state } -> gathering" )
280
- send ( state . controlling_process , { :ex_ice , self ( ) , { : gathering_state_change, :gathering } } )
348
+ notify ( state . on_gathering_state_change , { :gathering_state_change , :gathering } )
281
349
state = % { state | gathering_state: :gathering }
282
350
283
351
{ :ok , host_candidates } = Gatherer . gather_host_candidates ( ip_filter: state . ip_filter )
284
352
285
353
for cand <- host_candidates do
286
- send (
287
- state . controlling_process ,
288
- { :ex_ice , self ( ) , { :new_candidate , Candidate . marshal ( cand ) } }
289
- )
354
+ notify ( state . on_new_candidate , { :new_candidate , Candidate . marshal ( cand ) } )
290
355
end
291
356
292
357
# TODO should we override?
@@ -512,7 +577,7 @@ defmodule ExICE.ICEAgent do
512
577
{ :noreply , state }
513
578
end
514
579
else
515
- send ( state . controlling_process , { :ex_ice , self ( ) , { : data, packet } } )
580
+ notify ( state . on_data , { :data , packet } )
516
581
{ :noreply , state }
517
582
end
518
583
end
@@ -949,7 +1014,7 @@ defmodule ExICE.ICEAgent do
949
1014
)
950
1015
951
1016
Logger . debug ( "New srflx candidate: #{ inspect ( c ) } " )
952
- send ( state . controlling_process , { :ex_ice , self ( ) , { : new_candidate, Candidate . marshal ( c ) } } )
1017
+ notify ( state . on_new_candidate , { :new_candidate , Candidate . marshal ( c ) } )
953
1018
add_srflx_cand ( c , state )
954
1019
955
1020
cand ->
@@ -1292,12 +1357,12 @@ defmodule ExICE.ICEAgent do
1292
1357
cond do
1293
1358
state . gathering_state == :new and transaction_in_progress? ->
1294
1359
Logger . debug ( "Gathering state change: new -> gathering" )
1295
- send ( state . controlling_process , { :ex_ice , self ( ) , { : gathering_state_change, :gathering } } )
1360
+ notify ( state . on_gathering_state_change , { :gathering_state_change , :gathering } )
1296
1361
% { state | gathering_state: :gathering }
1297
1362
1298
1363
state . gathering_state == :gathering and not transaction_in_progress? ->
1299
1364
Logger . debug ( "Gathering state change: gathering -> complete" )
1300
- send ( state . controlling_process , { :ex_ice , self ( ) , { : gathering_state_change, :complete } } )
1365
+ notify ( state . on_gathering_state_change , { :gathering_state_change , :complete } )
1301
1366
% { state | gathering_state: :complete }
1302
1367
1303
1368
true ->
@@ -1346,7 +1411,7 @@ defmodule ExICE.ICEAgent do
1346
1411
end
1347
1412
1348
1413
Logger . debug ( "Gathering state change: #{ state . gathering_state } -> new" )
1349
- send ( state . controlling_process , { :ex_ice , self ( ) , { : gathering_state_change, :new } } )
1414
+ notify ( state . on_gathering_state_change , { :gathering_state_change , :new } )
1350
1415
1351
1416
% {
1352
1417
state
@@ -1404,7 +1469,7 @@ defmodule ExICE.ICEAgent do
1404
1469
@ spec change_connection_state ( atom ( ) , map ( ) ) :: map ( )
1405
1470
def change_connection_state ( new_conn_state , state ) do
1406
1471
Logger . debug ( "Connection state change: #{ state . state } -> #{ new_conn_state } " )
1407
- send ( state . controlling_process , { :ex_ice , self ( ) , { : connection_state_change, new_conn_state } } )
1472
+ notify ( state . on_connection_state_change , { :connection_state_change , new_conn_state } )
1408
1473
% { state | state: new_conn_state }
1409
1474
end
1410
1475
@@ -1620,4 +1685,7 @@ defmodule ExICE.ICEAgent do
1620
1685
end
1621
1686
end
1622
1687
end
1688
+
1689
+ defp notify ( nil , _msg ) , do: :ok
1690
+ defp notify ( dst , msg ) , do: send ( dst , { :ex_ice , self ( ) , msg } )
1623
1691
end
0 commit comments