emqx私有tcp协议服务器开发---emqx_tcp_connection模块(4)

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。

猜你喜欢

转载自blog.csdn.net/qq513036862/article/details/110311755