1、处理客户端进来的数据包,然后调用 emqx_tcp_frame解析数据
2、客户端socket限速方法实现
3、客户端socket的active_n属性设置接口实现
4、客户端socket的相关的消息统计接口实现
%% 处理socket进来的空数据包
process_incoming(<<>>, Packets, State) ->
{keep_state, State, next_events(Packets)};
process_incoming(Data, Packets,State = #state{parse_state = ParseState}) ->
%% 解析数据
try emqx_tcp_frame:parse(Data, ParseState) of
%% 解析完成
{ok, NParseState} ->
NState = State#state{parse_state = NParseState},
{keep_state, NState, next_events(Packets)};
%% 解析完成,有剩余的数据包,继续处理
{ok, Packet, Rest, NParseState} ->
NState = State#state{parse_state = NParseState},
process_incoming(Rest, [Packet | Packets], NState);
%% 解析错误,直接关闭
{error, Reason} -> shutdown(Reason, State)
catch
error:Reason:Stk ->
begin
logger:log(error,#{}, #{report_cb => fun (_) ->
{'$logger_header'() ++
"Parse failed for ~p~n\n "
" Stacktrace:~p~nError data:~p",
[Reason, Stk, Data]}
end,
mfa => {emqx_tcp_connection, process_incoming, 2},
line => 378})
end,
shutdown(parse_error, State)
end.
%% 取出所有数据包,然后反转list
next_events(Packets) when is_list(Packets) ->
[next_events(Packet)|| Packet <- lists:reverse(Packets)];
%% 针对每个数据包,发送异步处理
next_events(Packet) ->{next_event, cast, {incoming, Packet}}.
handle_incoming(Packet, SuccFun,State = #state{pstate = PState}) ->
case emqx_tcp_protocol:received(Packet, PState) of
{ok, NPState} -> SuccFun(State#state{pstate = NPState});
{error, Reason} -> shutdown(Reason, State);
{error, Reason, NPState} ->
shutdown(Reason, State#state{pstate = NPState});
{stop, Error, NPState} ->
stop(Error, State#state{pstate = NPState})
end.
ensure_rate_limit(State = #state{rate_limit = Rl}) ->
Limiters = [{Rl,#state.rate_limit, emqx_pd:reset_counter(incoming_bytes)}],
ensure_rate_limit(Limiters, State).
ensure_rate_limit([], State) -> State;
ensure_rate_limit([{undefined, _Pos, _Cnt} | Limiters],State) ->
ensure_rate_limit(Limiters, State);
ensure_rate_limit([{Rl, Pos, Cnt} | Limiters], State) ->
case esockd_rate_limit:check(Cnt, Rl) of
{0, Rl1} ->
ensure_rate_limit(Limiters,setelement(Pos, State, Rl1));
{Pause, Rl1} ->
begin
logger:log(debug,
#{},
#{report_cb =>
fun (_) ->
{'$logger_header'() ++
"Rate limit pause connection ~pms",
[Pause]}
end,
mfa => {emqx_tcp_connection, ensure_rate_limit, 1},
line => 418})
end,
TRef = erlang:send_after(Pause,
self(),
activate_socket),
setelement(Pos,
State#state{sockstate = blocked, limit_timer = TRef},
Rl1)
end.
activate_socket(#state{sockstate = blocked}) -> ok;
activate_socket(#state{transport = Transport,socket = Socket, active_n = N}) ->
case Transport:setopts(Socket, [{active, N}]) of
ok -> ok;
{error, Reason} ->
self() ! {shutdown, Reason},
ok
end.
%% 统计定时
ensure_stats_timer(State = #state{enable_stats = true,stats_timer = undefined,
idle_timeout = IdleTimeout}) ->
State#state{stats_timer = emqx_misc:start_timer(IdleTimeout, emit_stats)};
ensure_stats_timer(State) -> State.
reply(From, Reply, State) -> {keep_state, State, [{reply, From, Reply}]}.
shutdown(Reason = {shutdown, _}, State) ->stop(Reason, State);
shutdown(Reason, State) -> stop({shutdown, Reason}, State).
stop(Reason, State) -> {stop, Reason, State}.
接下来将分析emqx_tcp_frame。