ejabberd_listener模块启动分为两部分
1 启动端口监听
查看ejabberd_app.erl文件,启动过程语句
%%%启动一个supervisor,并启动和监控定义子进程
Sup = ejabberd_sup:start_link()
其中启动项包括ejabberd_listener:start_link/0
Listener =
{ejabberd_listener,
{ejabberd_listener, start_link, []},
permanent,
infinity,
supervisor,
[ejabberd_listener]},
以下为程序启动跟踪流程
start_link() ->
supervisor:start_link({local, ejabberd_listeners}, ?MODULE, []).
init(_) ->
%%%新建listen_sockets表
ets:new(listen_sockets, [named_table, public]),
%%%端口绑定
bind_tcp_ports(),
{ok, {
{one_for_one, 10, 1}, []}}.
bind_tcp_ports() ->
%%%获取配置文件信息
case ejabberd_config:get_option(listen, fun validate_cfg/1) of
undefined ->
ignore;
Ls ->
lists:foreach(
fun({
Port, Module, Opts}) ->
ModuleRaw = strip_frontend(Module),
case ModuleRaw:socket_type() of
independent -> ok;
_ ->
bind_tcp_port(Port, Module, Opts)
end
end, Ls)
end.
注:查看ejabberd_config:get_option/2执行结果,由此可知,配置文件需监听3端口详细配置
(可调用执行ejabberd_config:get_option(listen,fun ejabberd_listener:validate_cfg/1).)
[{
{5222,{0,0,0,0},tcp},
ejabberd_c2s,
[{
access,c2s},{
shaper,c2s_shaper},{
max_stanza_size,65536}]},
{
{5269,{0,0,0,0},tcp},ejabberd_s2s_in,[]},
{
{5280,{0,0,0,0},tcp},
ejabberd_http,
[{
captcha,true},
{
http_bind,true},
{
web_admin,true},
{
request_handlers,[{<<"/websocket">>,ejabberd_http_ws}]}]}]
继续跟踪
bind_tcp_port(PortIP, Module, RawOpts) ->
try check_listener_options(RawOpts) of
ok ->
{
Port, IPT, IPS, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts),
{_Opts, SockOpts} = prepare_opts(IPT, IPV, OptsClean),
case Proto of
udp -> ok;
_ ->
%%%TCP
ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS),
%%%监听端口成功,插入listen_sockets表
ets:insert(listen_sockets, {
PortIP, ListenSocket}),
ok
end
catch
throw:{error, Error} ->