diff --git a/src/quic/sdlan_quic_channel.erl b/src/quic/sdlan_quic_channel.erl index b0e38c7..de81b2b 100644 --- a/src/quic/sdlan_quic_channel.erl +++ b/src/quic/sdlan_quic_channel.erl @@ -64,7 +64,8 @@ bytes_recv = 0, %% 离线回调函数 - offline_cb :: undefined | fun() + offline_cb :: undefined | fun(), + close_reason = undefined }). %%%=================================================================== @@ -170,32 +171,32 @@ handle_event(info, {quic, new_stream, Stream, Opts}, _StateName, State) -> {keep_state, State}; handle_event(info, {quic, stream_closed, Stream, Props}, _StateName, State = #state{stream = Stream}) -> - {stop, {stream_closed, Props}, State}; + expected_stop({stream_closed, Props}, State); handle_event(info, {quic, peer_send_shutdown, Stream, _Props}, _StateName, State = #state{stream = Stream}) -> - {stop, peer_send_shutdown, State}; + expected_stop(peer_send_shutdown, State); handle_event(info, {quic, peer_send_aborted, Stream, ErrorCode}, _StateName, State = #state{stream = Stream}) -> - {stop, {peer_send_aborted, ErrorCode}, State}; + expected_stop({peer_send_aborted, ErrorCode}, State); handle_event(info, {quic, peer_receive_aborted, Stream, ErrorCode}, _StateName, State = #state{stream = Stream}) -> - {stop, {peer_receive_aborted, ErrorCode}, State}; + expected_stop({peer_receive_aborted, ErrorCode}, State); handle_event(info, {quic, send_shutdown_complete, Stream, _Props}, _StateName, State = #state{stream = Stream}) -> - {stop, connection_shutdown, State}; + expected_stop(connection_shutdown, State); handle_event(info, {quic, passive, Stream, _Props}, _StateName, State = #state{stream = Stream, stream_active_n = StreamActiveN}) -> ok = quicer:setopt(Stream, active, StreamActiveN), {keep_state, State}; handle_event(info, {quic, closed, Conn, Props}, _StateName, State = #state{conn = Conn}) -> - {stop, {connection_closed, Props}, State}; + expected_stop({connection_closed, Props}, State); handle_event(info, {quic, transport_shutdown, Conn, Props}, _StateName, State = #state{conn = Conn}) -> - {stop, {transport_shutdown, Props}, State}; + expected_stop({transport_shutdown, Props}, State); handle_event(info, {quic, shutdown, Conn, ErrorCode}, _StateName, State = #state{conn = Conn}) -> - {stop, {connection_shutdown_by_peer, ErrorCode}, State}; + expected_stop({connection_shutdown_by_peer, ErrorCode}, State); %% 处理quicer相关的信息, 需要转换成内部能够识别的frame消息 handle_event(info, {quic, Data, Stream, _Props}, _StateName, State = #state{stream = Stream, buf = Buf, max_packet_size = MaxPacketSize, bytes_recv = BytesRecv, frames_recv = FramesRecv}) when is_binary(Data) -> @@ -392,7 +393,7 @@ handle_event(info, {timeout, TimerRef, ping_ticker}, _, State = #state{ping_time {keep_state, schedule_ping(State#state{ping_counter = 0, ping_timer = undefined})}; false -> logger:debug("[sdlan_channel] client_id: ~p, ping losted", [ClientId]), - {stop, heartbeat_timeout, State#state{ping_counter = 0, ping_timer = undefined}} + expected_stop(heartbeat_timeout, State#state{ping_counter = 0, ping_timer = undefined}) end; handle_event(info, {timeout, _TimerRef, ping_ticker}, _, State) -> @@ -418,7 +419,7 @@ handle_event({call, From}, debug_info, StateName, State) -> {keep_state, State, [{reply, From, debug_info(StateName, State)}]}; handle_event(info, {'EXIT', _, _}, _StateName, State) -> - {stop, connection_closed, State}; + expected_stop(connection_closed, State); handle_event(EventType, Info, StateName, State) -> logger:notice("[sdlan_quic_channel] state: ~p, state_name: ~p, event_type: ~p, info: ~p", [State, StateName, EventType, Info]), @@ -429,10 +430,10 @@ handle_event(EventType, Info, StateName, State) -> %% terminate. It should be the opposite of Module:init/1 and do any %% necessary cleaning up. When it returns, the gen_statem terminates with %% Reason. The return value is ignored. -terminate(Reason, _StateName, _State = #state{conn = Conn, stream = Stream, offline_cb = OfflineCb}) -> +terminate(Reason, _StateName, _State = #state{conn = Conn, stream = Stream, offline_cb = OfflineCb, close_reason = CloseReason}) -> Stream /= undefined andalso quicer:close_stream(Stream, 1000), quicer:close_connection(Conn), - logger:warning("[sdlan_quic_conn] terminate closed with reason: ~p", [Reason]), + logger:notice("[sdlan_quic_conn] terminate closed with reason: ~p, close_reason: ~p", [Reason, CloseReason]), %% 触发客户端的离线逻辑 is_function(OfflineCb) andalso OfflineCb(), ok. @@ -489,6 +490,10 @@ get_rules(SrcIdentityId, DstIdentityId) when is_integer(SrcIdentityId), is_integ DstPolicyIds = identity_policy_ets:get_policies(DstIdentityId), rule_ets:get_rules(SrcPolicyIds, DstPolicyIds). +expected_stop(Reason, State) -> + logger:notice("[sdlan_quic_channel] expected close: ~p", [Reason]), + {stop, normal, State#state{close_reason = Reason}}. + schedule_ping(State = #state{heartbeat_sec = HeartbeatSec}) -> State#state{ping_timer = erlang:start_timer(heartbeat_ms(HeartbeatSec), self(), ping_ticker)}.