fix transport
This commit is contained in:
parent
ec023584bd
commit
1cf007f946
@ -31,7 +31,6 @@
|
|||||||
{keyfile, "server.key"},
|
{keyfile, "server.key"},
|
||||||
{limits, [
|
{limits, [
|
||||||
{max_packet_size, 16384},
|
{max_packet_size, 16384},
|
||||||
{socket_active_n, 100},
|
|
||||||
%% 单位为秒
|
%% 单位为秒
|
||||||
{heartbeat_sec, 15}
|
{heartbeat_sec, 15}
|
||||||
]}
|
]}
|
||||||
|
|||||||
@ -31,7 +31,6 @@
|
|||||||
{keyfile, "server.key"},
|
{keyfile, "server.key"},
|
||||||
{limits, [
|
{limits, [
|
||||||
{max_packet_size, 16384},
|
{max_packet_size, 16384},
|
||||||
{socket_active_n, 100},
|
|
||||||
%% 单位为秒
|
%% 单位为秒
|
||||||
{heartbeat_sec, 15}
|
{heartbeat_sec, 15}
|
||||||
]}
|
]}
|
||||||
|
|||||||
@ -118,24 +118,8 @@ handle_event(info, {quic, dgram_state_changed, Conn, Opts = #{dgram_send_enabled
|
|||||||
|
|
||||||
handle_event(info, {quic, new_stream, Stream, Opts}, waiting_stream, State = #state{max_packet_size = MaxPacketSize, heartbeat_sec = HeartbeatSec}) ->
|
handle_event(info, {quic, new_stream, Stream, Opts}, waiting_stream, State = #state{max_packet_size = MaxPacketSize, heartbeat_sec = HeartbeatSec}) ->
|
||||||
logger:debug("[sdlan_quic_transport] call new_stream: ~p, opts: ~p", [Stream, Opts]),
|
logger:debug("[sdlan_quic_transport] call new_stream: ~p, opts: ~p", [Stream, Opts]),
|
||||||
Ipv6Assist = case application:get_env(sdlan, ipv6_assist_info) of
|
|
||||||
{ok, {V6Bytes, Port}} ->
|
|
||||||
#'SDLV6Info' {
|
|
||||||
v6 = V6Bytes,
|
|
||||||
port = Port
|
|
||||||
};
|
|
||||||
_ ->
|
|
||||||
undefined
|
|
||||||
end,
|
|
||||||
%% 发送欢迎消息
|
%% 发送欢迎消息
|
||||||
WelcomePkt = sdlan_pb:encode_msg(#'SDLWelcome'{
|
quic_send(Stream, sdlan_session:welcome_packet(MaxPacketSize, HeartbeatSec)),
|
||||||
version = 1,
|
|
||||||
max_bidi_streams = 1,
|
|
||||||
max_packet_size = MaxPacketSize,
|
|
||||||
heartbeat_sec = HeartbeatSec,
|
|
||||||
ipv6_assist = Ipv6Assist
|
|
||||||
}),
|
|
||||||
quic_send(Stream, <<?PACKET_WELCOME, WelcomePkt/binary>>),
|
|
||||||
logger:debug("[sdlan_quic_transport] get stream: ~p, send welcome", [Stream]),
|
logger:debug("[sdlan_quic_transport] get stream: ~p, send welcome", [Stream]),
|
||||||
|
|
||||||
{next_state, initialized, State#state{stream = Stream}};
|
{next_state, initialized, State#state{stream = Stream}};
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
%% API
|
%% API
|
||||||
-export([new/1, state_name/1, handle_frame/2, handle_timeout/2]).
|
-export([new/1, state_name/1, handle_frame/2, handle_timeout/2]).
|
||||||
-export([send_event/2, command/4, close/1, debug_info/1]).
|
-export([send_event/2, command/4, close/1, debug_info/1]).
|
||||||
|
-export([welcome_packet/2]).
|
||||||
-export([test_rules/2]).
|
-export([test_rules/2]).
|
||||||
-export_type([state/0]).
|
-export_type([state/0]).
|
||||||
|
|
||||||
@ -71,6 +72,26 @@ test_rules(SrcIdentityId, DstIdentityId) when is_integer(SrcIdentityId), is_inte
|
|||||||
state_name(#state{status = Status}) ->
|
state_name(#state{status = Status}) ->
|
||||||
Status.
|
Status.
|
||||||
|
|
||||||
|
-spec welcome_packet(MaxPacketSize :: integer(), HeartbeatSec :: integer()) -> binary().
|
||||||
|
welcome_packet(MaxPacketSize, HeartbeatSec) ->
|
||||||
|
Ipv6Assist = case application:get_env(sdlan, ipv6_assist_info) of
|
||||||
|
{ok, {V6Bytes, Port}} ->
|
||||||
|
#'SDLV6Info' {
|
||||||
|
v6 = V6Bytes,
|
||||||
|
port = Port
|
||||||
|
};
|
||||||
|
_ ->
|
||||||
|
undefined
|
||||||
|
end,
|
||||||
|
WelcomePkt = sdlan_pb:encode_msg(#'SDLWelcome'{
|
||||||
|
version = 1,
|
||||||
|
max_bidi_streams = 1,
|
||||||
|
max_packet_size = MaxPacketSize,
|
||||||
|
heartbeat_sec = HeartbeatSec,
|
||||||
|
ipv6_assist = Ipv6Assist
|
||||||
|
}),
|
||||||
|
<<?PACKET_WELCOME, WelcomePkt/binary>>.
|
||||||
|
|
||||||
-spec handle_frame(Frame :: binary(), State :: #state{}) ->
|
-spec handle_frame(Frame :: binary(), State :: #state{}) ->
|
||||||
{ok, NewState :: #state{}, Packets :: [binary()]} |
|
{ok, NewState :: #state{}, Packets :: [binary()]} |
|
||||||
{stop, Reason :: term(), NewState :: #state{}, Packets :: [binary()]}.
|
{stop, Reason :: term(), NewState :: #state{}, Packets :: [binary()]}.
|
||||||
|
|||||||
@ -13,8 +13,6 @@
|
|||||||
-behaviour(gen_statem).
|
-behaviour(gen_statem).
|
||||||
-behaviour(ranch_protocol).
|
-behaviour(ranch_protocol).
|
||||||
|
|
||||||
-define(SOCKET_ACTIVE_N, 100).
|
|
||||||
|
|
||||||
%% Ranch protocol callback
|
%% Ranch protocol callback
|
||||||
-export([start_link/4]).
|
-export([start_link/4]).
|
||||||
|
|
||||||
@ -25,17 +23,10 @@
|
|||||||
ref :: ranch:ref(),
|
ref :: ranch:ref(),
|
||||||
socket :: undefined | ssl:sslsocket(),
|
socket :: undefined | ssl:sslsocket(),
|
||||||
transport :: module(),
|
transport :: module(),
|
||||||
ok_msg :: atom(),
|
|
||||||
closed_msg :: atom(),
|
|
||||||
error_msg :: atom(),
|
|
||||||
passive_msg :: atom(),
|
|
||||||
|
|
||||||
max_packet_size = 16384,
|
max_packet_size = 16384,
|
||||||
heartbeat_sec = 15,
|
heartbeat_sec = 15,
|
||||||
socket_active_n = ?SOCKET_ACTIVE_N,
|
|
||||||
|
|
||||||
%% 累积器,用于处理协议framing的解析
|
|
||||||
buf = <<>>,
|
|
||||||
session :: sdlan_session:state(),
|
session :: sdlan_session:state(),
|
||||||
|
|
||||||
frames_recv = 0,
|
frames_recv = 0,
|
||||||
@ -58,20 +49,13 @@ start_link(Ref, Socket, Transport, Limits) ->
|
|||||||
init([Ref, Socket, Transport, Limits]) ->
|
init([Ref, Socket, Transport, Limits]) ->
|
||||||
MaxPacketSize = proplists:get_value(max_packet_size, Limits, 16384),
|
MaxPacketSize = proplists:get_value(max_packet_size, Limits, 16384),
|
||||||
HeartbeatSec = proplists:get_value(heartbeat_sec, Limits, 15),
|
HeartbeatSec = proplists:get_value(heartbeat_sec, Limits, 15),
|
||||||
SocketActiveN = proplists:get_value(socket_active_n, Limits, proplists:get_value(stream_active_n, Limits, ?SOCKET_ACTIVE_N)),
|
|
||||||
{OkMsg, ClosedMsg, ErrorMsg} = Transport:messages(),
|
|
||||||
Session = sdlan_session:new(HeartbeatSec),
|
Session = sdlan_session:new(HeartbeatSec),
|
||||||
{ok, handshaking, #state{
|
{ok, handshaking, #state{
|
||||||
ref = Ref,
|
ref = Ref,
|
||||||
socket = Socket,
|
socket = Socket,
|
||||||
transport = Transport,
|
transport = Transport,
|
||||||
ok_msg = OkMsg,
|
|
||||||
closed_msg = ClosedMsg,
|
|
||||||
error_msg = ErrorMsg,
|
|
||||||
passive_msg = passive_msg(OkMsg),
|
|
||||||
max_packet_size = MaxPacketSize,
|
max_packet_size = MaxPacketSize,
|
||||||
heartbeat_sec = HeartbeatSec,
|
heartbeat_sec = HeartbeatSec,
|
||||||
socket_active_n = SocketActiveN,
|
|
||||||
session = Session
|
session = Session
|
||||||
}}.
|
}}.
|
||||||
|
|
||||||
@ -80,38 +64,26 @@ callback_mode() ->
|
|||||||
|
|
||||||
handle_event(info, {handshake, Ref, Transport, Socket, Timeout}, handshaking,
|
handle_event(info, {handshake, Ref, Transport, Socket, Timeout}, handshaking,
|
||||||
State = #state{ref = Ref, transport = Transport, max_packet_size = MaxPacketSize,
|
State = #state{ref = Ref, transport = Transport, max_packet_size = MaxPacketSize,
|
||||||
heartbeat_sec = HeartbeatSec, socket_active_n = SocketActiveN}) ->
|
heartbeat_sec = HeartbeatSec}) ->
|
||||||
case Transport:handshake(Socket, [], Timeout) of
|
case Transport:handshake(Socket, [], Timeout) of
|
||||||
{ok, SslSocket} ->
|
{ok, SslSocket} ->
|
||||||
ok = Transport:setopts(SslSocket, [{mode, binary}, {active, SocketActiveN}]),
|
ok = Transport:setopts(SslSocket, [{mode, binary}, {packet, 2}, {active, true}]),
|
||||||
WelcomePkt = welcome_packet(MaxPacketSize, HeartbeatSec),
|
ssl_send(Transport, SslSocket, sdlan_session:welcome_packet(MaxPacketSize, HeartbeatSec)),
|
||||||
ssl_send(Transport, SslSocket, <<?PACKET_WELCOME, WelcomePkt/binary>>),
|
|
||||||
logger:debug("[sdlan_ssl_transport] ssl handshake ok, send welcome"),
|
logger:debug("[sdlan_ssl_transport] ssl handshake ok, send welcome"),
|
||||||
{next_state, initialized, State#state{socket = SslSocket}};
|
{next_state, initialized, State#state{socket = SslSocket}};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{stop, {ssl_handshake_failed, Reason}, State}
|
{stop, {ssl_handshake_failed, Reason}, State}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_event(info, {OkMsg, Socket, Data}, _StateName,
|
handle_event(info, {ssl, Socket, Data}, _StateName,
|
||||||
State = #state{socket = Socket, ok_msg = OkMsg, buf = Buf, max_packet_size = MaxPacketSize,
|
State = #state{socket = Socket, bytes_recv = BytesRecv, frames_recv = FramesRecv}) when is_binary(Data) ->
|
||||||
bytes_recv = BytesRecv, frames_recv = FramesRecv}) when is_binary(Data) ->
|
{keep_state, State#state{bytes_recv = BytesRecv + byte_size(Data), frames_recv = FramesRecv + 1},
|
||||||
case decode_frames(<<Buf/binary, Data/binary>>, MaxPacketSize) of
|
[{next_event, internal, {frame, Data}}]};
|
||||||
{error, Reason} ->
|
|
||||||
{stop, Reason, State};
|
|
||||||
{ok, NBuf, Frames} ->
|
|
||||||
Actions = [{next_event, internal, {frame, Frame}} || Frame <- Frames],
|
|
||||||
{keep_state, State#state{buf = NBuf, bytes_recv = BytesRecv + byte_size(Data), frames_recv = FramesRecv + length(Frames)}, Actions}
|
|
||||||
end;
|
|
||||||
|
|
||||||
handle_event(info, {PassiveMsg, Socket}, _StateName,
|
handle_event(info, {ssl_closed, Socket}, _StateName, State = #state{socket = Socket}) ->
|
||||||
State = #state{socket = Socket, transport = Transport, passive_msg = PassiveMsg, socket_active_n = SocketActiveN}) ->
|
|
||||||
ok = Transport:setopts(Socket, [{active, SocketActiveN}]),
|
|
||||||
{keep_state, State};
|
|
||||||
|
|
||||||
handle_event(info, {ClosedMsg, Socket}, _StateName, State = #state{socket = Socket, closed_msg = ClosedMsg}) ->
|
|
||||||
expected_stop(socket_closed, State);
|
expected_stop(socket_closed, State);
|
||||||
|
|
||||||
handle_event(info, {ErrorMsg, Socket, Reason}, _StateName, State = #state{socket = Socket, error_msg = ErrorMsg}) ->
|
handle_event(info, {ssl_error, Socket, Reason}, _StateName, State = #state{socket = Socket}) ->
|
||||||
expected_stop({socket_error, Reason}, State);
|
expected_stop({socket_error, Reason}, State);
|
||||||
|
|
||||||
%% 处理内部的包消息
|
%% 处理内部的包消息
|
||||||
@ -173,41 +145,10 @@ code_change(_OldVsn, StateName, State = #state{}, _Extra) ->
|
|||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
|
||||||
welcome_packet(MaxPacketSize, HeartbeatSec) ->
|
|
||||||
Ipv6Assist = case application:get_env(sdlan, ipv6_assist_info) of
|
|
||||||
{ok, {V6Bytes, Port}} ->
|
|
||||||
#'SDLV6Info' {
|
|
||||||
v6 = V6Bytes,
|
|
||||||
port = Port
|
|
||||||
};
|
|
||||||
_ ->
|
|
||||||
undefined
|
|
||||||
end,
|
|
||||||
sdlan_pb:encode_msg(#'SDLWelcome'{
|
|
||||||
version = 1,
|
|
||||||
max_bidi_streams = 1,
|
|
||||||
max_packet_size = MaxPacketSize,
|
|
||||||
heartbeat_sec = HeartbeatSec,
|
|
||||||
ipv6_assist = Ipv6Assist
|
|
||||||
}).
|
|
||||||
|
|
||||||
%% 有2种情况
|
|
||||||
%% 1. 收到了多个完整的请求
|
|
||||||
%% 2. 不完整,则不处理
|
|
||||||
-spec decode_frames(Buf :: binary(), MaxPacketSize :: integer()) -> {ok, RestBin::binary(), Frames :: list()} | {error, Reason :: any()}.
|
|
||||||
decode_frames(Buf, MaxPacketSize) when is_binary(Buf) ->
|
|
||||||
decode_frames0(Buf, MaxPacketSize, []).
|
|
||||||
decode_frames0(<<Len:16, _/binary>>, MaxPacketSize, _Frames) when Len > MaxPacketSize ->
|
|
||||||
{error, frame_too_large};
|
|
||||||
decode_frames0(<<Len:16, Frame:Len/binary, Rest/binary>>, MaxPacketSize, Frames) ->
|
|
||||||
decode_frames0(Rest, MaxPacketSize, [Frame|Frames]);
|
|
||||||
decode_frames0(Rest, _MaxPacketSize, Frames) ->
|
|
||||||
{ok, Rest, lists:reverse(Frames)}.
|
|
||||||
|
|
||||||
ssl_send(Transport, Socket, Packet) when is_binary(Packet) ->
|
ssl_send(Transport, Socket, Packet) when is_binary(Packet) ->
|
||||||
Len = byte_size(Packet),
|
Len = byte_size(Packet),
|
||||||
true = Len =< 65535,
|
true = Len =< 65535,
|
||||||
case Transport:send(Socket, <<Len:16, Packet/binary>>) of
|
case Transport:send(Socket, Packet) of
|
||||||
ok ->
|
ok ->
|
||||||
incr_counter(ssl_frames_sent, 1),
|
incr_counter(ssl_frames_sent, 1),
|
||||||
incr_counter(ssl_bytes_sent, Len + 2),
|
incr_counter(ssl_bytes_sent, Len + 2),
|
||||||
@ -226,14 +167,10 @@ expected_stop(Reason, State) ->
|
|||||||
next_state_name(_StateName, Session) ->
|
next_state_name(_StateName, Session) ->
|
||||||
sdlan_session:state_name(Session).
|
sdlan_session:state_name(Session).
|
||||||
|
|
||||||
passive_msg(OkMsg) ->
|
|
||||||
list_to_atom(atom_to_list(OkMsg) ++ "_passive").
|
|
||||||
|
|
||||||
debug_info(StateName, #state{
|
debug_info(StateName, #state{
|
||||||
session = Session,
|
session = Session,
|
||||||
frames_recv = FramesRecv,
|
frames_recv = FramesRecv,
|
||||||
bytes_recv = BytesRecv,
|
bytes_recv = BytesRecv,
|
||||||
socket_active_n = SocketActiveN,
|
|
||||||
heartbeat_sec = HeartbeatSec
|
heartbeat_sec = HeartbeatSec
|
||||||
}) ->
|
}) ->
|
||||||
ProcInfo = maps:from_list(process_info(self(), [message_queue_len, memory, reductions])),
|
ProcInfo = maps:from_list(process_info(self(), [message_queue_len, memory, reductions])),
|
||||||
@ -245,7 +182,6 @@ debug_info(StateName, #state{
|
|||||||
frames_sent => get_counter(ssl_frames_sent),
|
frames_sent => get_counter(ssl_frames_sent),
|
||||||
bytes_recv => BytesRecv,
|
bytes_recv => BytesRecv,
|
||||||
bytes_sent => get_counter(ssl_bytes_sent),
|
bytes_sent => get_counter(ssl_bytes_sent),
|
||||||
socket_active_n => SocketActiveN,
|
|
||||||
heartbeat_sec => HeartbeatSec
|
heartbeat_sec => HeartbeatSec
|
||||||
}).
|
}).
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user