diff --git a/docs/api.md b/docs/api.md index 58456ff..a51319c 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,6 +1,6 @@ # HTTP API 接口文档 -本文档根据 `src/http_handler` 下各 handler 的 `handle_request/4` 实现整理。 +本文档根据 `src/http` 下各 handler 的 `handle_request/4` 实现整理。 ## 通用说明 diff --git a/src/http_handler/api_handler.erl b/src/http/api_handler.erl similarity index 100% rename from src/http_handler/api_handler.erl rename to src/http/api_handler.erl diff --git a/src/http_handler/binlog_handler.erl b/src/http/binlog_handler.erl similarity index 100% rename from src/http_handler/binlog_handler.erl rename to src/http/binlog_handler.erl diff --git a/src/http_handler/http_protocol.erl b/src/http/http_protocol.erl similarity index 100% rename from src/http_handler/http_protocol.erl rename to src/http/http_protocol.erl diff --git a/src/http_handler/network_handler.erl b/src/http/network_handler.erl similarity index 100% rename from src/http_handler/network_handler.erl rename to src/http/network_handler.erl diff --git a/src/http_handler/node_handler.erl b/src/http/node_handler.erl similarity index 100% rename from src/http_handler/node_handler.erl rename to src/http/node_handler.erl diff --git a/src/http/sdlan_http_server.erl b/src/http/sdlan_http_server.erl new file mode 100644 index 0000000..cca72a8 --- /dev/null +++ b/src/http/sdlan_http_server.erl @@ -0,0 +1,40 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2026, +%%% @doc +%%% +%%% @end +%%% Created : 03. 5月 2026 15:06 +%%%------------------------------------------------------------------- +-module(sdlan_http_server). +-author("anlicheng"). + +%% API +-export([start/0]). + +%% 启动http服务 +start() -> + {ok, Props} = application:get_env(sdlan, http_server), + Acceptors = proplists:get_value(acceptors, Props, 50), + MaxConnections = proplists:get_value(max_connections, Props, 10240), + Backlog = proplists:get_value(backlog, Props, 1024), + Port = proplists:get_value(port, Props), + + Dispatcher = cowboy_router:compile([ + {'_', [ + {"/api/[...]", http_protocol, [api_handler]}, + {"/binlog", http_protocol, [binlog_handler]}, + {"/network/[...]", http_protocol, [network_handler]}, + {"/node/[...]", http_protocol, [node_handler]}, + {"/test/[...]", http_protocol, [test_handler]} + ]} + ]), + + TransOpts = [ + {port, Port}, + {num_acceptors, Acceptors}, + {backlog, Backlog}, + {max_connections, MaxConnections} + ], + {ok, Pid} = cowboy:start_clear(http_listener, TransOpts, #{env => #{dispatch => Dispatcher}}), + logger:debug("[iot_app] the http server start at: ~p, pid is: ~p", [Port, Pid]). \ No newline at end of file diff --git a/src/http_handler/test_handler.erl b/src/http/test_handler.erl similarity index 100% rename from src/http_handler/test_handler.erl rename to src/http/test_handler.erl diff --git a/src/quic/sdlan_quic_transport.erl b/src/quic/sdlan_quic_transport.erl index 37fa267..d4c5af2 100644 --- a/src/quic/sdlan_quic_transport.erl +++ b/src/quic/sdlan_quic_transport.erl @@ -156,8 +156,7 @@ handle_event(info, {quic, shutdown, Conn, ErrorCode}, _StateName, State = #state %% 处理quicer相关的信息, 需要转换成内部能够识别的frame消息 handle_event(info, {quic, Data, Stream, _Props}, _StateName, - State = #state{stream = Stream, buf = Buf, max_packet_size = MaxPacketSize}) - when is_binary(Data) -> + State = #state{stream = Stream, buf = Buf, max_packet_size = MaxPacketSize}) when is_binary(Data) -> case decode_frames(<>, MaxPacketSize) of {error, Reason} -> {stop, Reason, State}; @@ -170,10 +169,10 @@ handle_event(info, {quic, Data, Stream, _Props}, _StateName, handle_event(internal, {frame, Frame}, _StateName, State = #state{stream = Stream, session = Session}) -> case sdlan_session:handle_frame(Frame, Session) of {ok, NStateName, NSession, Packets} -> - send_packets(Stream, Packets), + quic_send(Stream, Packets), {next_state, NStateName, State#state{session = NSession}}; {stop, Reason, _NStateName, NSession, Packets} -> - send_packets(Stream, Packets), + quic_send(Stream, Packets), {stop, Reason, State#state{session = NSession}} end; @@ -189,7 +188,7 @@ handle_event(info, {timeout, TimerRef, ping_ticker}, _StateName, State = #state{ handle_event(cast, {send_event, Event}, _StateName, State = #state{stream = Stream, session = Session}) -> case sdlan_session:send_event(Event, Session) of {ok, NStateName, NSession, Packets} -> - send_packets(Stream, Packets), + quic_send(Stream, Packets), {next_state, NStateName, State#state{session = NSession}}; {error, not_registered} -> keep_state_and_data @@ -199,7 +198,7 @@ handle_event(cast, {send_event, Event}, _StateName, State = #state{stream = Stre handle_event(cast, {command, Ref, ReceiverPid, SubCommand}, _StateName, State = #state{stream = Stream, session = Session}) -> case sdlan_session:command(Ref, ReceiverPid, SubCommand, Session) of {ok, NStateName, NSession, Packets} -> - send_packets(Stream, Packets), + quic_send(Stream, Packets), {next_state, NStateName, State#state{session = NSession}}; {error, not_registered} -> keep_state_and_data @@ -249,11 +248,13 @@ decode_frames0(<>, MaxPacketSize, Frames) decode_frames0(Rest, _MaxPacketSize, Frames) -> {ok, Rest, lists:reverse(Frames)}. --spec quic_send(Stream :: quicer:stream_handle(), Packet :: binary()) -> no_return(). -quic_send(Stream, Packet) when is_binary(Packet) -> - Len = byte_size(Packet), +-spec quic_send(Stream :: quicer:stream_handle(), Data :: iodata()) -> no_return(). +quic_send(_Stream, []) -> + ok; +quic_send(Stream, Data) -> + Len = iolist_size(Data), true = Len =< 65535, - case quicer:send(Stream, <>) of + case quicer:send(Stream, [<>, Data]) of {ok, _} -> incr_counter(quic_frames_sent, 1), incr_counter(quic_bytes_sent, Len + 2), @@ -262,9 +263,6 @@ quic_send(Stream, Packet) when is_binary(Packet) -> exit({quic_send_failed, Reason}) end. -send_packets(Stream, Packets) -> - lists:foreach(fun(Packet) -> quic_send(Stream, Packet) end, Packets). - expected_stop(Reason, State) -> logger:notice("[sdlan_quic_transport] expected close: ~p", [Reason]), {stop, normal, State#state{close_reason = Reason}}. diff --git a/src/sdlan_app.erl b/src/sdlan_app.erl index 93552f0..4d0c3e1 100644 --- a/src/sdlan_app.erl +++ b/src/sdlan_app.erl @@ -33,37 +33,12 @@ start(_StartType, _StartArgs) -> identity_policy_ets:init(), rule_ets:init(), - start_http_server(), + sdlan_http_server:start(), + sdlan_ssl_server:start(), + sdlan_sup:start_link(). stop(_State) -> ok. -%% internal functions - -%% 启动http服务 -start_http_server() -> - {ok, Props} = application:get_env(sdlan, http_server), - Acceptors = proplists:get_value(acceptors, Props, 50), - MaxConnections = proplists:get_value(max_connections, Props, 10240), - Backlog = proplists:get_value(backlog, Props, 1024), - Port = proplists:get_value(port, Props), - - Dispatcher = cowboy_router:compile([ - {'_', [ - {"/api/[...]", http_protocol, [api_handler]}, - {"/binlog", http_protocol, [binlog_handler]}, - {"/network/[...]", http_protocol, [network_handler]}, - {"/node/[...]", http_protocol, [node_handler]}, - {"/test/[...]", http_protocol, [test_handler]} - ]} - ]), - - TransOpts = [ - {port, Port}, - {num_acceptors, Acceptors}, - {backlog, Backlog}, - {max_connections, MaxConnections} - ], - {ok, Pid} = cowboy:start_clear(http_listener, TransOpts, #{env => #{dispatch => Dispatcher}}), - logger:debug("[iot_app] the http server start at: ~p, pid is: ~p", [Port, Pid]). +%% internal functions \ No newline at end of file diff --git a/src/quic/sdlan_session.erl b/src/sdlan_session.erl similarity index 98% rename from src/quic/sdlan_session.erl rename to src/sdlan_session.erl index 35de870..43fe486 100644 --- a/src/quic/sdlan_session.erl +++ b/src/sdlan_session.erl @@ -242,15 +242,9 @@ close(#session{offline_cb = OfflineCb}) -> ok. -spec debug_info(Session :: #session{}) -> map(). -debug_info(#session{ - status = Status, - client_id = ClientId, - network_id = NetworkId, - mac = Mac, - ip = Ip, - pending_commands = PendingCommands, - heartbeat_sec = HeartbeatSec -}) -> +debug_info(#session{ status = Status, client_id = ClientId, network_id = NetworkId, mac = Mac, ip = Ip, + pending_commands = PendingCommands, heartbeat_sec = HeartbeatSec}) -> + #{ session_state => Status, client_id => ClientId, @@ -377,4 +371,4 @@ stop_timeout_result(Reason, Session = #session{status = StateName}) -> heartbeat_ms(HeartbeatSec) when is_integer(HeartbeatSec), HeartbeatSec > 0 -> HeartbeatSec * 1000; heartbeat_ms(_) -> - ?PING_TICKER. + ?PING_TICKER. \ No newline at end of file diff --git a/src/sdlan_sup.erl b/src/sdlan_sup.erl index 512dc75..72ed0b0 100644 --- a/src/sdlan_sup.erl +++ b/src/sdlan_sup.erl @@ -90,8 +90,6 @@ init([]) -> modules => ['sdlan_quic_server'] }, - sdlan_ssl_server:child_spec(), - #{ id => sdlan_sync_mysql, start => {sdlan_sync_mysql, start_link, []}, diff --git a/src/ssl/sdlan_ssl_server.erl b/src/ssl/sdlan_ssl_server.erl index c213d26..77777f4 100644 --- a/src/ssl/sdlan_ssl_server.erl +++ b/src/ssl/sdlan_ssl_server.erl @@ -10,20 +10,10 @@ -author("anlicheng"). %% API --export([start/0, child_spec/0]). +-export([start/0]). %% 启动ssl服务 start() -> - {TransOpts, Limits, Port} = listener_options(), - {ok, Pid} = ranch:start_listener(ssl_server, ranch_ssl, TransOpts, sdlan_ssl_transport, Limits), - logger:debug("[sdlan_ssl_server] the ssl server start at: ~p, pid is: ~p", [Port, Pid]), - {ok, Pid}. - -child_spec() -> - {TransOpts, Limits} = listener_options(), - ranch:child_spec(ssl_server, ranch_ssl, TransOpts, sdlan_ssl_transport, Limits). - -listener_options() -> {ok, Props} = application:get_env(sdlan, ssl_server), Acceptors = proplists:get_value(acceptors, Props, 50), MaxConnections = proplists:get_value(max_connections, Props, 10240), @@ -48,4 +38,5 @@ listener_options() -> {keyfile, KeyFile} ] }, - {TransOpts, Limits}. + {ok, Pid} = ranch:start_listener(ssl_server, ranch_ssl, TransOpts, sdlan_ssl_transport, Limits), + logger:debug("[sdlan_ssl_server] the ssl server start at: ~p, pid is: ~p", [Port, Pid]). \ No newline at end of file