From 2ff9cf51ce7e72857cf2fc4c36ad543adec5d161 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Fri, 13 Feb 2026 13:40:24 +0800 Subject: [PATCH] decode frames --- apps/sdlan/src/quic/quic_client.erl | 23 ++++++++++++-- apps/sdlan/src/quic/sdlan_quic_channel.erl | 35 +++++++++++++++++++--- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/apps/sdlan/src/quic/quic_client.erl b/apps/sdlan/src/quic/quic_client.erl index 3d6e252..2016b9e 100644 --- a/apps/sdlan/src/quic/quic_client.erl +++ b/apps/sdlan/src/quic/quic_client.erl @@ -19,8 +19,27 @@ start() -> do_start() -> Port = 1365, {ok, Conn} = quicer:connect("localhost", Port, [{alpn, ["punchnet/1.0"]}, {verify, none}], 5000), + + receive + {quic, connected, Conn} -> + ok + after 1000 -> + ok + end, + {ok, Stm} = quicer:start_stream(Conn, []), - {ok, 4} = quicer:send(Stm, <<"ping">>), - logger:debug("[quic_client] client send success"), + receive + {quic, stream_started, Stm} -> + ok + after 1000 -> + ok + end, + + Data = <<"ping">>, + Len = byte_size(Data), + Payload = <>, + + {ok, SendLen} = quicer:send(Stm, Payload), + logger:debug("[quic_client] client send success: ~p", [SendLen]), receive {quic, <<"pong">>, Stm, _Props} -> ok end, ok = quicer:close_connection(Conn). \ No newline at end of file diff --git a/apps/sdlan/src/quic/sdlan_quic_channel.erl b/apps/sdlan/src/quic/sdlan_quic_channel.erl index 514b993..0b9f19e 100644 --- a/apps/sdlan/src/quic/sdlan_quic_channel.erl +++ b/apps/sdlan/src/quic/sdlan_quic_channel.erl @@ -11,6 +11,8 @@ -behaviour(gen_statem). +-define(MAX_FRAME_LEN, 16384). + %% API -export([start_link/1]). @@ -19,7 +21,9 @@ -record(state, { conn :: quicer:connection_handle(), - stream_handle :: undefined | quicer:stream_handle() + stream_handle :: undefined | quicer:stream_handle(), + %% 累积器,用于处理协议framing的解析 + buf = <<>> }). %%%=================================================================== @@ -65,11 +69,21 @@ handle_event(internal, do_init, initializing, State = #state{conn = Conn}) -> {stop, Reason, State} end; -%% 处理quicer相关的信息 -handle_event(info, {quic, Msg, Stream, _Props}, _StateName, State = #state{stream_handle = Stream}) -> - logger:debug("[sdlan_quic_channel] get message: ~p", [Msg]), +handle_event(info, {frame, Frame}, _StateName, State = #state{}) -> + logger:debug("[sdlan_quic_channel] get frame: ~p", [Frame]), {keep_state, State}; +%% 处理quicer相关的信息 +handle_event(info, {quic, Data, Stream, _Props}, _StateName, State = #state{stream_handle = Stream, buf = Buf}) -> + logger:debug("[sdlan_quic_channel] get message: ~p", [Data]), + case decode_frames(<>) of + {error, Reason} -> + {stop, Reason, State}; + {ok, NBuf, Frames} -> + Actions = [{next_event, info, {frame, Frame}} || Frame <- Frames], + {keep_state, State#state{buf = NBuf}, Actions} + end; + handle_event(info, {quic_closed, Stream, _Props}, _StateName, State = #state{conn = Conn, stream_handle = Stream}) -> quicer:close_connection(Conn), {stop, connection_closed, State}; @@ -106,3 +120,16 @@ code_change(_OldVsn, StateName, State = #state{}, _Extra) -> %%%=================================================================== %%% Internal functions %%%=================================================================== + +%% 有2种情况 +%% 1. 收到了多个完整的请求 +%% 2. 不完整,则不处理 +-spec decode_frames(Buf :: binary()) -> {ok, RestBin::binary(), Frames :: list()} | {error, Reason :: any()}. +decode_frames(Buf) when is_binary(Buf) -> + decode_frames0(Buf, []). +decode_frames0(<>, _Frames) when Len > ?MAX_FRAME_LEN -> + {error, frame_too_large}; +decode_frames0(<>, Frames) -> + decode_frames0(Rest, [Frame|Frames]); +decode_frames0(Rest, Frames) -> + {ok, Rest, lists:reverse(Frames)}. \ No newline at end of file