add ssl server
This commit is contained in:
parent
6b2777b5b6
commit
4109f06ce4
@ -1,6 +1,6 @@
|
|||||||
# HTTP API 接口文档
|
# HTTP API 接口文档
|
||||||
|
|
||||||
本文档根据 `src/http_handler` 下各 handler 的 `handle_request/4` 实现整理。
|
本文档根据 `src/http` 下各 handler 的 `handle_request/4` 实现整理。
|
||||||
|
|
||||||
## 通用说明
|
## 通用说明
|
||||||
|
|
||||||
|
|||||||
40
src/http/sdlan_http_server.erl
Normal file
40
src/http/sdlan_http_server.erl
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @author anlicheng
|
||||||
|
%%% @copyright (C) 2026, <COMPANY>
|
||||||
|
%%% @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]).
|
||||||
@ -156,8 +156,7 @@ handle_event(info, {quic, shutdown, Conn, ErrorCode}, _StateName, State = #state
|
|||||||
|
|
||||||
%% 处理quicer相关的信息, 需要转换成内部能够识别的frame消息
|
%% 处理quicer相关的信息, 需要转换成内部能够识别的frame消息
|
||||||
handle_event(info, {quic, Data, Stream, _Props}, _StateName,
|
handle_event(info, {quic, Data, Stream, _Props}, _StateName,
|
||||||
State = #state{stream = Stream, buf = Buf, max_packet_size = MaxPacketSize})
|
State = #state{stream = Stream, buf = Buf, max_packet_size = MaxPacketSize}) when is_binary(Data) ->
|
||||||
when is_binary(Data) ->
|
|
||||||
case decode_frames(<<Buf/binary, Data/binary>>, MaxPacketSize) of
|
case decode_frames(<<Buf/binary, Data/binary>>, MaxPacketSize) of
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{stop, Reason, State};
|
{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}) ->
|
handle_event(internal, {frame, Frame}, _StateName, State = #state{stream = Stream, session = Session}) ->
|
||||||
case sdlan_session:handle_frame(Frame, Session) of
|
case sdlan_session:handle_frame(Frame, Session) of
|
||||||
{ok, NStateName, NSession, Packets} ->
|
{ok, NStateName, NSession, Packets} ->
|
||||||
send_packets(Stream, Packets),
|
quic_send(Stream, Packets),
|
||||||
{next_state, NStateName, State#state{session = NSession}};
|
{next_state, NStateName, State#state{session = NSession}};
|
||||||
{stop, Reason, _NStateName, NSession, Packets} ->
|
{stop, Reason, _NStateName, NSession, Packets} ->
|
||||||
send_packets(Stream, Packets),
|
quic_send(Stream, Packets),
|
||||||
{stop, Reason, State#state{session = NSession}}
|
{stop, Reason, State#state{session = NSession}}
|
||||||
end;
|
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}) ->
|
handle_event(cast, {send_event, Event}, _StateName, State = #state{stream = Stream, session = Session}) ->
|
||||||
case sdlan_session:send_event(Event, Session) of
|
case sdlan_session:send_event(Event, Session) of
|
||||||
{ok, NStateName, NSession, Packets} ->
|
{ok, NStateName, NSession, Packets} ->
|
||||||
send_packets(Stream, Packets),
|
quic_send(Stream, Packets),
|
||||||
{next_state, NStateName, State#state{session = NSession}};
|
{next_state, NStateName, State#state{session = NSession}};
|
||||||
{error, not_registered} ->
|
{error, not_registered} ->
|
||||||
keep_state_and_data
|
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}) ->
|
handle_event(cast, {command, Ref, ReceiverPid, SubCommand}, _StateName, State = #state{stream = Stream, session = Session}) ->
|
||||||
case sdlan_session:command(Ref, ReceiverPid, SubCommand, Session) of
|
case sdlan_session:command(Ref, ReceiverPid, SubCommand, Session) of
|
||||||
{ok, NStateName, NSession, Packets} ->
|
{ok, NStateName, NSession, Packets} ->
|
||||||
send_packets(Stream, Packets),
|
quic_send(Stream, Packets),
|
||||||
{next_state, NStateName, State#state{session = NSession}};
|
{next_state, NStateName, State#state{session = NSession}};
|
||||||
{error, not_registered} ->
|
{error, not_registered} ->
|
||||||
keep_state_and_data
|
keep_state_and_data
|
||||||
@ -249,11 +248,13 @@ decode_frames0(<<Len:16, Frame:Len/binary, Rest/binary>>, MaxPacketSize, Frames)
|
|||||||
decode_frames0(Rest, _MaxPacketSize, Frames) ->
|
decode_frames0(Rest, _MaxPacketSize, Frames) ->
|
||||||
{ok, Rest, lists:reverse(Frames)}.
|
{ok, Rest, lists:reverse(Frames)}.
|
||||||
|
|
||||||
-spec quic_send(Stream :: quicer:stream_handle(), Packet :: binary()) -> no_return().
|
-spec quic_send(Stream :: quicer:stream_handle(), Data :: iodata()) -> no_return().
|
||||||
quic_send(Stream, Packet) when is_binary(Packet) ->
|
quic_send(_Stream, []) ->
|
||||||
Len = byte_size(Packet),
|
ok;
|
||||||
|
quic_send(Stream, Data) ->
|
||||||
|
Len = iolist_size(Data),
|
||||||
true = Len =< 65535,
|
true = Len =< 65535,
|
||||||
case quicer:send(Stream, <<Len:16, Packet/binary>>) of
|
case quicer:send(Stream, [<<Len:16>>, Data]) of
|
||||||
{ok, _} ->
|
{ok, _} ->
|
||||||
incr_counter(quic_frames_sent, 1),
|
incr_counter(quic_frames_sent, 1),
|
||||||
incr_counter(quic_bytes_sent, Len + 2),
|
incr_counter(quic_bytes_sent, Len + 2),
|
||||||
@ -262,9 +263,6 @@ quic_send(Stream, Packet) when is_binary(Packet) ->
|
|||||||
exit({quic_send_failed, Reason})
|
exit({quic_send_failed, Reason})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
send_packets(Stream, Packets) ->
|
|
||||||
lists:foreach(fun(Packet) -> quic_send(Stream, Packet) end, Packets).
|
|
||||||
|
|
||||||
expected_stop(Reason, State) ->
|
expected_stop(Reason, State) ->
|
||||||
logger:notice("[sdlan_quic_transport] expected close: ~p", [Reason]),
|
logger:notice("[sdlan_quic_transport] expected close: ~p", [Reason]),
|
||||||
{stop, normal, State#state{close_reason = Reason}}.
|
{stop, normal, State#state{close_reason = Reason}}.
|
||||||
|
|||||||
@ -33,37 +33,12 @@ start(_StartType, _StartArgs) ->
|
|||||||
identity_policy_ets:init(),
|
identity_policy_ets:init(),
|
||||||
rule_ets:init(),
|
rule_ets:init(),
|
||||||
|
|
||||||
start_http_server(),
|
sdlan_http_server:start(),
|
||||||
|
sdlan_ssl_server:start(),
|
||||||
|
|
||||||
sdlan_sup:start_link().
|
sdlan_sup:start_link().
|
||||||
|
|
||||||
stop(_State) ->
|
stop(_State) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
%% internal functions
|
%% 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]).
|
|
||||||
|
|||||||
@ -242,15 +242,9 @@ close(#session{offline_cb = OfflineCb}) ->
|
|||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec debug_info(Session :: #session{}) -> map().
|
-spec debug_info(Session :: #session{}) -> map().
|
||||||
debug_info(#session{
|
debug_info(#session{ status = Status, client_id = ClientId, network_id = NetworkId, mac = Mac, ip = Ip,
|
||||||
status = Status,
|
pending_commands = PendingCommands, heartbeat_sec = HeartbeatSec}) ->
|
||||||
client_id = ClientId,
|
|
||||||
network_id = NetworkId,
|
|
||||||
mac = Mac,
|
|
||||||
ip = Ip,
|
|
||||||
pending_commands = PendingCommands,
|
|
||||||
heartbeat_sec = HeartbeatSec
|
|
||||||
}) ->
|
|
||||||
#{
|
#{
|
||||||
session_state => Status,
|
session_state => Status,
|
||||||
client_id => ClientId,
|
client_id => ClientId,
|
||||||
@ -90,8 +90,6 @@ init([]) ->
|
|||||||
modules => ['sdlan_quic_server']
|
modules => ['sdlan_quic_server']
|
||||||
},
|
},
|
||||||
|
|
||||||
sdlan_ssl_server:child_spec(),
|
|
||||||
|
|
||||||
#{
|
#{
|
||||||
id => sdlan_sync_mysql,
|
id => sdlan_sync_mysql,
|
||||||
start => {sdlan_sync_mysql, start_link, []},
|
start => {sdlan_sync_mysql, start_link, []},
|
||||||
|
|||||||
@ -10,20 +10,10 @@
|
|||||||
-author("anlicheng").
|
-author("anlicheng").
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start/0, child_spec/0]).
|
-export([start/0]).
|
||||||
|
|
||||||
%% 启动ssl服务
|
%% 启动ssl服务
|
||||||
start() ->
|
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),
|
{ok, Props} = application:get_env(sdlan, ssl_server),
|
||||||
Acceptors = proplists:get_value(acceptors, Props, 50),
|
Acceptors = proplists:get_value(acceptors, Props, 50),
|
||||||
MaxConnections = proplists:get_value(max_connections, Props, 10240),
|
MaxConnections = proplists:get_value(max_connections, Props, 10240),
|
||||||
@ -48,4 +38,5 @@ listener_options() ->
|
|||||||
{keyfile, KeyFile}
|
{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]).
|
||||||
Loading…
x
Reference in New Issue
Block a user