@@ -27,8 +27,25 @@ defmodule ExICE.Priv.Candidate do
27
27
@ callback send_data ( t ( ) , :inet . ip_address ( ) , :inet . port_number ( ) , binary ( ) ) ::
28
28
{ :ok , t ( ) } | { :error , term ( ) , t ( ) }
29
29
30
- @ spec priority ( type ( ) ) :: integer ( )
31
- def priority ( type ) do
30
+ @ spec priority! ( % { :inet . ip_address ( ) => non_neg_integer ( ) } , :inet . ip_address ( ) , type ( ) ) ::
31
+ non_neg_integer ( )
32
+ def priority! ( local_preferences , base_address , type ) do
33
+ local_preference = Map . fetch! ( local_preferences , base_address )
34
+ do_priority ( local_preference , type )
35
+ end
36
+
37
+ @ spec priority ( % { :inet . ip_address ( ) => non_neg_integer ( ) } , :inet . ip_address ( ) , type ( ) ) ::
38
+ { % { :inet . ip_address ( ) => non_neg_integer ( ) } , non_neg_integer ( ) }
39
+ def priority ( local_preferences , base_address , type ) do
40
+ local_preference =
41
+ Map . get ( local_preferences , base_address ) || generate_local_preference ( local_preferences )
42
+
43
+ local_preferences = Map . put ( local_preferences , base_address , local_preference )
44
+
45
+ { local_preferences , do_priority ( local_preference , type ) }
46
+ end
47
+
48
+ defp do_priority ( local_preference , type ) do
32
49
type_preference =
33
50
case type do
34
51
:host -> 126
@@ -37,14 +54,25 @@ defmodule ExICE.Priv.Candidate do
37
54
:relay -> 0
38
55
end
39
56
40
- # That's not fully correct as according to RFC 8445 sec. 5.1.2.1 we should:
41
- # * use value of 65535 when there is only one IP address
42
- # * use different values when there are multiple IP addresses
43
- local_preference = 65_535
44
-
45
57
2 ** 24 * type_preference + 2 ** 8 * local_preference + 2 ** 0 * ( 256 - 1 )
46
58
end
47
59
60
+ defp generate_local_preference ( local_preferences , attempts \\ 200 )
61
+
62
+ defp generate_local_preference ( _local_preferences , 0 ) ,
63
+ do: raise ( "Couldn't generate local preference" )
64
+
65
+ defp generate_local_preference ( local_preferences , attempts ) do
66
+ # this should give us a number from 0 to 2**16-1
67
+ << pref :: 16 >> = :crypto . strong_rand_bytes ( 2 )
68
+
69
+ if Map . has_key? ( local_preferences , pref ) do
70
+ generate_local_preference ( local_preferences , attempts - 1 )
71
+ else
72
+ pref
73
+ end
74
+ end
75
+
48
76
@ spec foundation ( type ( ) , :inet . ip_address ( ) | String . t ( ) , :inet . ip_address ( ) | nil , atom ( ) ) ::
49
77
integer ( )
50
78
def foundation ( type , ip , stun_turn_ip , transport ) do
0 commit comments