%% 回调处理
handle({call, From}, info, State) -> reply(From, info(State), State);
handle({call, From}, stats, State) -> reply(From, stats(State), State);
handle({call, From}, kick, State) ->
ok = gen_statem:reply(From, ok),
shutdown(kicked, State);
handle({call, From}, Req, State) ->
begin
logger:log(error,#{}, #{report_cb =>
fun (_) ->{'$logger_header'() ++ "Unexpected call: ~p",[Req]} end,
mfa => {emqx_tcp_connection, handle, 3}, line => 261})
end,
reply(From, ignored, State);
handle(cast, Msg, State) ->
begin
logger:log(error,#{}, #{report_cb => fun (_) ->
{'$logger_header'() ++ "Unexpected cast: ~p", [Msg]} end,
mfa => {emqx_tcp_connection, handle, 3}, line => 266}) end,
{keep_state, State};
handle(info, {Inet, _Sock, Data},State = #state{pstate = PState})
when Inet == tcp; Inet == ssl ->
Oct = iolist_size(Data),
begin
logger:log(debug, #{},#{report_cb =>
fun (_) -> {'$logger_header'() ++ "RECV ~p", [Data]} end,
mfa => {emqx_tcp_connection, handle, 3}, line => 273})
end,
%% 计算进来的数据包个数
emqx_pd:inc_counter(incoming_bytes, Oct),
%% 计算接收了多少个字节数据
ok = emqx_metrics:inc('bytes.received', Oct),
%% 检出虚拟机,除非gc从操作
NPState = emqx_tcp_protocol:maybe_gc_and_check_oom(Oct,PState),
%% 处理数据包
process_incoming(Data, [],State#state{pstate = NPState});
%% 错误处理
handle(info, {Error, _Sock, Reason}, State)
when Error == tcp_error; Error == ssl_error ->
shutdown(Reason, State);
%% 关闭处理
handle(info, {Closed, _Sock}, State)
when Closed == tcp_closed; Closed == ssl_closed ->
shutdown(closed, State);
%%
handle(info, {Passive, _Sock}, State)
when Passive == tcp_passive; Passive == ssl_passive ->
NState = ensure_rate_limit(State),
ok = activate_socket(NState),
{keep_state, NState};
%% 设置
handle(info, activate_socket, State) ->
ok = activate_socket(State#state{sockstate = running}),
{keep_state,State#state{sockstate = running, limit_timer = undefined}};
handle(info, {inet_reply, _Sock, ok}, State) -> {keep_state, State};
handle(info, {inet_reply, _Sock, {error, Reason}}, State) ->shutdown(Reason, State);
%% 超时处理
handle(info, {timeout, Timer, emit_stats},
State = #state{stats_timer = Timer, pstate = PState}) ->
ClientId = emqx_tcp_protocol:client_id(PState),
%% 设置客户端状态
emqx_cm:set_chan_stats(ClientId, stats(State)),
%% 统计定时停止
{keep_state,ensure_stats_timer(State#state{stats_timer = undefined})};
handle(info, {timeout, _Ref, {keepalive, check}},
State = #state{transport = Transport, socket = Socket,keepalive = Keepalive}) ->
case Transport:getstat(Socket, [recv_oct]) of
{ok, [{recv_oct, RecvOct}]} ->
case emqx_keepalive:check(RecvOct, Keepalive) of
{ok, NKeepalive} ->
{keep_state, State#state{keepalive = NKeepalive}};
{error, timeout} -> shutdown(keepalive_timeout, State)
end;
{error, Reason} -> shutdown({sockerr, Reason}, State)
end;
handle(info, {shutdown, discard, {ClientId, ByPid}},State) ->
begin
logger:log(error,#{}, #{report_cb =>fun (_) ->
{'$logger_header'() ++ "Discarded by ~s:~p", [ClientId, ByPid]} end,
mfa => {emqx_tcp_connection, handle, 3}, line => 329})
end,
shutdown(discard, State);
%% 冲突处理
handle(info, {shutdown, conflict, {ClientId, NewPid}},State) ->
begin
logger:log(warning,#{}, #{report_cb => fun (_) ->
{'$logger_header'() ++"Clientid '~s' conflict with ~p",
[ClientId, NewPid]} end,
mfa => {emqx_tcp_connection, handle, 3}, line => 333})
end,
shutdown(conflict, State);
handle(info, {shutdown, Reason}, State) ->shutdown(Reason, State);
handle(info, Info, State) ->
begin
logger:log(error,#{},#{report_cb =>fun (_) ->
{'$logger_header'() ++ "Unexpected info: ~p",[Info]} end,
mfa => {emqx_tcp_connection, handle, 3}, line => 340})
end,
{keep_state, State}.
code_change(_Vsn, State, Data, _Extra) ->
{ok, State, Data}.
%% 终止进程
terminate(Reason, _StateName,#state{transport = Transport, socket = Socket,
pstate = PState}) ->
begin
logger:log(debug, #{},#{report_cb =>fun (_) ->
{'$logger_header'() ++ "Terminated for ~p",[Reason]} end,
mfa => {emqx_tcp_connection, terminate, 3}, line => 349})
end,
%% 快速关闭
Transport:fast_close(Socket),
%% 关闭原因处理
case {PState, Reason} of
{undefined, _} -> ok;
{_, {shutdown, Error}} ->
emqx_tcp_protocol:terminate(Error, PState);
{_, Reason} ->
emqx_tcp_protocol:terminate(Reason, PState)
end.
emqx私有tcp协议服务器开发---emqx_tcp_connection模块(3)
猜你喜欢
转载自blog.csdn.net/qq513036862/article/details/110311205
今日推荐
周排行