1818-export ([get_downstream_safe /2 ,
1919 get_downstream_pool /1 ,
2020 get_netloc /1 ,
21- get_netloc_safe /1 ,
2221 get_secret /0 ,
22+ get_default_dc /0 ,
2323 status /0 ,
2424 update /0 ]).
2525
3737-define (TAB , ? MODULE ).
3838-define (IPS_KEY (DcId ), {id , DcId }).
3939-define (IDS_KEY , dc_ids ).
40+ -define (DEFAULT_DC_KEY , default_dc ).
4041-define (SECRET_URL , " https://core.telegram.org/getProxySecret" ).
4142-define (CONFIG_URL , " https://core.telegram.org/getProxyConfig" ).
4243
@@ -65,9 +66,11 @@ get_downstream_safe(DcId, Opts) ->
6566 error ({pool_empty , DcId , Pool })
6667 end ;
6768 not_found ->
68- [{? IDS_KEY , L }] = ets :lookup (? TAB , ? IDS_KEY ),
69- NewDcId = random_choice (L ),
70- get_downstream_safe (NewDcId , Opts )
69+ case get_default_dc () of
70+ undefined -> error ({no_pool , DcId });
71+ DcId -> error ({no_pool , DcId }); % default == requested, avoid loop
72+ NewDcId -> get_downstream_safe (NewDcId , Opts )
73+ end
7174 end .
7275
7376get_downstream_pool (DcId ) ->
@@ -78,17 +81,6 @@ get_downstream_pool(DcId) ->
7881 not_found
7982 end .
8083
81- -spec get_netloc_safe (dc_id ()) -> {dc_id (), netloc ()}.
82- get_netloc_safe (DcId ) ->
83- case get_netloc (DcId ) of
84- {ok , Addr } -> {DcId , Addr };
85- not_found ->
86- [{? IDS_KEY , L }] = ets :lookup (? TAB , ? IDS_KEY ),
87- NewDcId = random_choice (L ),
88- % % Get random DC; it might return 0 and recurse aggain
89- get_netloc_safe (NewDcId )
90- end .
91-
9284get_netloc (DcId ) ->
9385 Key = ? IPS_KEY (DcId ),
9486 case ets :lookup (? TAB , Key ) of
@@ -107,6 +99,13 @@ get_secret() ->
10799 [{_ , Key }] = ets :lookup (? TAB , key ),
108100 Key .
109101
102+ -spec get_default_dc () -> dc_id () | undefined .
103+ get_default_dc () ->
104+ case ets :lookup (? TAB , ? DEFAULT_DC_KEY ) of
105+ [{? DEFAULT_DC_KEY , DcId }] -> DcId ;
106+ [] -> undefined
107+ end .
108+
110109-spec status () -> [mtp_dc_pool :status ()].
111110status () ->
112111 [{? IDS_KEY , L }] = ets :lookup (? TAB , ? IDS_KEY ),
@@ -130,7 +129,7 @@ init([]) ->
130129 #{timeout => {env , ? APP , conf_refresh_interval , 3600 },
131130 unit => second }),
132131 Tab = ets :new (? TAB , [set ,
133- public ,
132+ protected ,
134133 named_table ,
135134 {read_concurrency , true }]),
136135 State = # state {tab = Tab ,
@@ -189,17 +188,23 @@ update_key(Tab) ->
189188update_config (Tab ) ->
190189 Url = application :get_env (mtproto_proxy , proxy_config_url , ? CONFIG_URL ),
191190 {ok , Body } = http_get (Url ),
192- Downstreams = parse_config (Body ),
191+ { DefaultDc , Downstreams } = parse_config (Body ),
193192 update_downstreams (Downstreams , Tab ),
194- update_ids (Downstreams , Tab ).
193+ update_ids (Downstreams , DefaultDc , Tab ).
195194
196195parse_config (Body ) ->
197196 Lines = string :lexemes (Body , " \n " ),
198- ProxyLines = lists :filter (
199- fun (" proxy_for " ++ _ ) -> true ;
200- (_ ) -> false
201- end , Lines ),
202- [parse_downstream (Line ) || Line <- ProxyLines ].
197+ {DefaultDc , Downstreams } =
198+ lists :foldl (
199+ fun (" default " ++ _ = Line , {_ , Ds }) ->
200+ [" default" , DcIdStr ] = string :lexemes (Line , " ;" ),
201+ {list_to_integer (DcIdStr ), Ds };
202+ (" proxy_for " ++ _ = Line , {Def , Ds }) ->
203+ {Def , [parse_downstream (Line ) | Ds ]};
204+ (_ , Acc ) ->
205+ Acc
206+ end , {undefined , []}, Lines ),
207+ {DefaultDc , lists :reverse (Downstreams )}.
203208
204209parse_downstream (Line ) ->
205210 [" proxy_for" ,
@@ -231,9 +236,10 @@ update_downstreams(Downstreams, Tab) ->
231236 end ,
232237 maps :keys (ByDc )).
233238
234- update_ids (Downstreams , Tab ) ->
239+ update_ids (Downstreams , DefaultDc , Tab ) ->
235240 Ids = lists :usort ([DcId || {DcId , _ , _ } <- Downstreams ]),
236- true = ets :insert (Tab , {? IDS_KEY , Ids }).
241+ true = ets :insert (Tab , {? IDS_KEY , Ids }),
242+ true = ets :insert (Tab , {? DEFAULT_DC_KEY , DefaultDc }).
237243
238244update_ip () ->
239245 case application :get_env (? APP , ip_lookup_services ) of
@@ -283,15 +289,22 @@ random_choice(L) ->
283289-include_lib (" eunit/include/eunit.hrl" ).
284290
285291parse_test () ->
286- Config = (" # force_probability 1 10
287- proxy_for 1 149.154.175.50:8888;
288- proxy_for -1 149.154.175.50:8888;
289- proxy_for 2 149.154.162.39:80;
290- proxy_for 2 149.154.162.33:80;" ),
292+ Config = (" # force_probability 1 10\n "
293+ " default 2;\n "
294+ " proxy_for 1 149.154.175.50:8888;\n "
295+ " proxy_for -1 149.154.175.50:8888;\n "
296+ " proxy_for 2 149.154.162.39:80;\n "
297+ " proxy_for 2 149.154.162.33:80;" ),
291298 Expect = [{1 , {149 , 154 , 175 , 50 }, 8888 },
292299 {- 1 , {149 , 154 , 175 , 50 }, 8888 },
293300 {2 , {149 , 154 , 162 , 39 }, 80 },
294301 {2 , {149 , 154 , 162 , 33 },80 }],
295- ? assertEqual (Expect , parse_config (Config )).
302+ ? assertEqual ({2 , Expect }, parse_config (Config )).
303+
304+ parse_no_default_test () ->
305+ Config = (" proxy_for 1 149.154.175.50:8888;\n "
306+ " proxy_for 2 149.154.162.39:80;" ),
307+ {DefaultDc , _ } = parse_config (Config ),
308+ ? assertEqual (undefined , DefaultDc ).
296309
297310-endif .
0 commit comments