1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(erl_distribution).
21
22-behaviour(supervisor).
23
24-include_lib("kernel/include/logger.hrl").
25
26-export([start_link/0,start_link/3,init/1,start/1,stop/0]).
27
28-define(DBG,erlang:display([?MODULE,?LINE])).
29
30%% Called during system start-up.
31
32start_link() ->
33    do_start_link([{sname,shortnames},{name,longnames}]).
34
35%% Called from net_kernel:start/1 to start distribution after the
36%% system has already started.
37
38start(Args) ->
39    C = #{id => net_sup_dynamic,
40          start => {?MODULE,start_link,[Args,false,net_sup_dynamic]},
41          restart => permanent,
42          shutdown => 1000,
43          type => supervisor,
44          modules => [erl_distribution]},
45    supervisor:start_child(kernel_sup, C).
46
47%% Stop distribution.
48
49stop() ->
50    case supervisor:terminate_child(kernel_sup, net_sup_dynamic) of
51	ok ->
52	    supervisor:delete_child(kernel_sup, net_sup_dynamic);
53	Error ->
54	    case whereis(net_sup) of
55		Pid when is_pid(Pid) ->
56		    %% Dist. started through -sname | -name flags
57		    {error, not_allowed};
58		_ ->
59		    Error
60	    end
61    end.
62
63%%%
64%%% Internal helper functions.
65%%%
66
67%% Helper start function.
68
69start_link(Args, CleanHalt, NetSup) ->
70    supervisor:start_link({local,net_sup}, ?MODULE, [Args,CleanHalt,NetSup]).
71
72init(NetArgs) ->
73    Epmd =
74	case init:get_argument(no_epmd) of
75	    {ok, [[]]} ->
76		[];
77	    _ ->
78		EpmdMod = net_kernel:epmd_module(),
79		[#{id => EpmdMod,
80                   start => {EpmdMod,start_link,[]},
81                   restart => permanent,
82                   shutdown => 2000,
83                   type => worker,
84                   modules => [EpmdMod]}]
85	end,
86    Auth = #{id => auth,
87             start => {auth,start_link,[]},
88             restart => permanent,
89             shutdown => 2000,
90             type => worker,
91             modules => [auth]},
92    Kernel = #{id => net_kernel,
93               start => {net_kernel,start_link,NetArgs},
94               restart => permanent,
95               shutdown => 2000,
96               type => worker,
97               modules => [net_kernel]},
98    EarlySpecs = net_kernel:protocol_childspecs(),
99    SupFlags = #{strategy => one_for_all,
100                 intensity => 0,
101                 period => 1},
102    {ok, {SupFlags, EarlySpecs ++ Epmd ++ [Auth,Kernel]}}.
103
104do_start_link([{Arg,Flag}|T]) ->
105    case init:get_argument(Arg) of
106	{ok,[[Name]]} ->
107	    start_link([list_to_atom(Name),Flag|ticktime()], true, net_sup);
108        {ok,[[Name]|_Rest]} ->
109            ?LOG_WARNING("Multiple -~p given to erl, using the first, ~p",
110                         [Arg, Name]),
111	    start_link([list_to_atom(Name),Flag|ticktime()], true, net_sup);
112        {ok,[Invalid|_]} ->
113            ?LOG_ERROR("Invalid -~p given to erl, ~ts",
114                       [Arg, lists:join(" ",Invalid)]),
115	    do_start_link(T);
116	_ ->
117	    do_start_link(T)
118    end;
119do_start_link([]) ->
120    ignore.
121
122ticktime() ->
123    %% catch, in case the system was started with boot file start_old,
124    %% i.e. running without the application_controller.
125    %% Time is given in seconds. The net_kernel tick time is
126    %% Time/4 milliseconds.
127    case catch application:get_env(net_ticktime) of
128	{ok, Value} when is_integer(Value), Value > 0 ->
129	    [Value * 250]; %% i.e. 1000 / 4 = 250 ms.
130	_ ->
131	    []
132    end.
133