接着上一篇,继续分析下面的代码
%% 速率限制未定义返回
rate_limit_info(undefined) -> #{};
%% 调用esockd 库函里面的方法获取限速相关信息
rate_limit_info(Limit) -> esockd_rate_limit:info(Limit).
%% 通过进程id 获取进程的统计信息
stats(CPid) when is_pid(CPid) -> call(CPid, stats);
stats(#state{transport = Transport, socket = Socket,pstate = PState}) ->
SockStats = case Transport:getstat(Socket,
[recv_oct, %% 接收字节数
recv_cnt, %% 接收消息条数
send_oct, %% 发送字节数
send_cnt, %% 发送消息条数
send_pend])
of
{ok, Ss} -> Ss;
{error, _} -> []
end,
%% 收集相关的统计统计信息返回
lists:append([SockStats,
emqx_misc:proc_stats(),
emqx_tcp_protocol:stats(PState)]).
kick(CPid) -> call(CPid, kick).
call(CPid, Req) -> gen_statem:call(CPid, Req, infinity).
%% 连接服务进程初始化
init({Transport, RawSocket, Options}) ->
%% 等待socket连接
case Transport:wait(RawSocket) of
%% 返回连接,然后进行初始化
{ok, Socket} -> do_init(Transport, Socket, Options);
%% 错误,然后关闭socket
{error, Reason}
when Reason =:= enotconn;
Reason =:= einval;
Reason =:= closed ->
Transport:fast_close(RawSocket),
exit(normal);
%% 超时,然后关闭
{error, timeout} ->
Transport:fast_close(RawSocket),
exit({shutdown, ssl_upgrade_timeout});
%% 其他原因,关闭
{error, Reason} ->
Transport:fast_close(RawSocket),
exit(Reason)
end.
%% 客户端socket连接初始化
do_init(Transport, Socket, Options) ->
%% 确保该连接之前的连接退出
{ok, Peername} = Transport:ensure_ok_or_exit(peername,
[Socket]),
{ok, Sockname} = Transport:ensure_ok_or_exit(sockname,
[Socket]),
Peercert = Transport:ensure_ok_or_exit(peercert,
[Socket]),
emqx_logger:set_metadata_peername(esockd:format(Peername)),
%% 获取限速信息
RateLimit = init_limiter(proplists:get_value(rate_limit,Options)),
%% 一次性从内核读多少数据包
ActiveN = proplists:get_value(active_n, Options, 100),
%% 发送函数定义
SendFun = fun (Packet, Opts) ->
%% 序列号数据包
Data = emqx_tcp_frame:serialize(Packet, Opts),
%% 异步发送数据包
case Transport:async_send(Socket, Data) of
ok -> {ok, Data};
{error, Reason} -> {error, Reason}
end
end,
%% 连接信息封装
ConnInfo = #{socktype => Transport:type(Socket),
peername => Peername, sockname => Sockname,
peercert => Peercert, sendfun => SendFun,
conn_mod => emqx_tcp_connection},
%% 初始化PState
PState = emqx_tcp_protocol:init(ConnInfo, Options),
%% 数据报最大设置
MaxSize = proplists:get_value(max_packet_size,Options, 65535),
%% 数据解析状态初始化
ParseState = emqx_tcp_frame:initial_parse_state(#{max_size => MaxSize}),
%% 统计配置是否开启
EnableStats = proplists:get_value(enable_stats,Options,true),
%% 空闲超时设置
IdleTimout = proplists:get_value(idle_timeout,Options,30000),
%% 客户端socket状态封装
State = #state{transport = Transport, socket = Socket,
peername = Peername, sockstate = running,
active_n = ActiveN, rate_limit = RateLimit,
pstate = PState, parse_state = ParseState,
enable_stats = EnableStats, idle_timeout = IdleTimout},
%% 进入客户端socket进程循环
gen_statem:enter_loop(emqx_tcp_connection,
[{hibernate_after, 2 * IdleTimout}],
idle,State,self(),[IdleTimout]).
%% 限速设置
init_limiter(undefined) -> undefined;
init_limiter({Rate, Burst}) ->esockd_rate_limit:new(Rate, Burst).
%% 回调
callback_mode() -> [state_functions, state_enter].
idle(enter, _, State) ->
ok = activate_socket(State),
keep_state_and_data;
idle(timeout, _Timeout, State) ->
{stop, {shutdown, idle_timeout}, State};
idle(cast, {incoming, Packet}, State) ->
handle_incoming(Packet,
fun (NState) -> {next_state, connected, NState} end,
State);
idle(EventType, Content, State) ->
handle(EventType, Content, State).
%% 连接进入
connected(enter, _, _State) -> keep_state_and_data;
%% 异步处理进来的数据包
connected(cast, {incoming, Packet}, State) ->
%%处理进来的数据包
handle_incoming(Packet,fun (NState) -> {keep_state, NState} end, State);
%% 处理消息投递
connected(info, {deliver, _Topic, Message},State = #state{pstate = PState}) ->
case emqx_tcp_protocol:deliver({message, Message},PState) of
{ok, NPState} ->
NState = State#state{pstate = NPState},
{keep_state, NState};
{error, Reason} -> shutdown(Reason, State)
end;
%% 处理keepalive
connected(info, {keepalive, start, Interval}, State) ->
Keepalive = emqx_keepalive:init(Interval),
%% 启动定时
_ = emqx_misc:start_timer(Interval, {keepalive, check}),
{keep_state, State#state{keepalive = Keepalive}};
connected(EventType, Content, State) ->
handle(EventType, Content, State).