fix ssl_channel
This commit is contained in:
parent
33227d5613
commit
a219095670
@ -13,7 +13,7 @@
|
|||||||
-define(INFLIGHT_TIMEOUT, 60000).
|
-define(INFLIGHT_TIMEOUT, 60000).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([pub/4, container_call/3, cancel_command_call/2, command/2, activate/2]).
|
-export([pub/4, container_call/3, cancel_command_call/2, activate/2]).
|
||||||
|
|
||||||
-export([start_link/3, stop/2]).
|
-export([start_link/3, stop/2]).
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
@ -41,15 +41,13 @@
|
|||||||
pub(Pid, Topic, Qos, Content) when is_pid(Pid), is_binary(Topic), is_integer(Qos), is_binary(Content) ->
|
pub(Pid, Topic, Qos, Content) when is_pid(Pid), is_binary(Topic), is_integer(Qos), is_binary(Content) ->
|
||||||
gen_server:cast(Pid, {pub, Topic, Qos, Content}).
|
gen_server:cast(Pid, {pub, Topic, Qos, Content}).
|
||||||
|
|
||||||
%% 向通道中写入消息
|
-spec activate(Pid :: pid(), Auth :: boolean()) -> Ref :: reference().
|
||||||
-spec command(Pid :: pid(), Command :: activate | deactivate) -> no_return().
|
|
||||||
command(Pid, Command) when is_pid(Pid), (Command =:= activate orelse Command =:= deactivate) ->
|
|
||||||
gen_server:cast(Pid, {command, Command}).
|
|
||||||
|
|
||||||
-spec activate(Pid :: pid(), Auth :: boolean()) -> no_return().
|
|
||||||
activate(Pid, Auth) when is_pid(Pid), is_boolean(Auth) ->
|
activate(Pid, Auth) when is_pid(Pid), is_boolean(Auth) ->
|
||||||
Command = case Auth of true -> activate; false -> deactivate end,
|
Command = case Auth of true -> activate; false -> deactivate end,
|
||||||
gen_server:cast(Pid, {command, Command}).
|
Ref = make_ref(),
|
||||||
|
ReceiverPid = self(),
|
||||||
|
gen_server:cast(Pid, {command_call, ReceiverPid, Ref, {auth, Command}}),
|
||||||
|
Ref.
|
||||||
|
|
||||||
-spec container_call(Pid :: pid(), ReceiverPid :: pid(), Request :: map()) -> Ref :: reference().
|
-spec container_call(Pid :: pid(), ReceiverPid :: pid(), Request :: map()) -> Ref :: reference().
|
||||||
container_call(Pid, ReceiverPid, Request) when is_pid(Pid), is_pid(ReceiverPid), is_map(Request) ->
|
container_call(Pid, ReceiverPid, Request) when is_pid(Pid), is_pid(ReceiverPid), is_map(Request) ->
|
||||||
@ -100,17 +98,6 @@ handle_cast({pub, Topic, Qos, Content}, State = #state{transport = Transport, so
|
|||||||
Transport:send(Socket, Packet),
|
Transport:send(Socket, Packet),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
|
||||||
%% 发送Command消息
|
|
||||||
handle_cast({command, Command}, State = #state{transport = Transport, socket = Socket, inflight = Inflight}) ->
|
|
||||||
Ref = make_ref(),
|
|
||||||
Packet = term_to_binary({command, Ref, {auth, Command}}),
|
|
||||||
Transport:send(Socket, Packet),
|
|
||||||
|
|
||||||
TimerRef = erlang:start_timer(?INFLIGHT_TIMEOUT, self(), {command_timeout, Ref}),
|
|
||||||
CommandInfo = #inflight_command{receiver_pid = undefined, timer_ref = TimerRef},
|
|
||||||
|
|
||||||
{noreply, State#state{inflight = maps:put(Ref, CommandInfo, Inflight)}};
|
|
||||||
|
|
||||||
%% iot 请求 efka 时使用 command/command_response 语义。
|
%% iot 请求 efka 时使用 command/command_response 语义。
|
||||||
handle_cast({command_call, ReceiverPid, Ref, Body}, State = #state{transport = Transport, socket = Socket, inflight = Inflight}) ->
|
handle_cast({command_call, ReceiverPid, Ref, Body}, State = #state{transport = Transport, socket = Socket, inflight = Inflight}) ->
|
||||||
Packet = term_to_binary({command, Ref, Body}),
|
Packet = term_to_binary({command, Ref, Body}),
|
||||||
@ -123,8 +110,9 @@ handle_cast({command_call, ReceiverPid, Ref, Body}, State = #state{transport = T
|
|||||||
|
|
||||||
handle_info({timeout, TimerRef, {command_timeout, Ref}}, State = #state{inflight = Inflight}) ->
|
handle_info({timeout, TimerRef, {command_timeout, Ref}}, State = #state{inflight = Inflight}) ->
|
||||||
case maps:get(Ref, Inflight, undefined) of
|
case maps:get(Ref, Inflight, undefined) of
|
||||||
#inflight_command{timer_ref = TimerRef} ->
|
#inflight_command{receiver_pid = ReceiverPid, timer_ref = TimerRef} ->
|
||||||
logger:warning("[ws_channel] command timeout, ref: ~p", [Ref]),
|
logger:warning("[ws_channel] command timeout, ref: ~p", [Ref]),
|
||||||
|
reply_command_timeout(ReceiverPid, Ref),
|
||||||
{noreply, State#state{inflight = maps:remove(Ref, Inflight)}};
|
{noreply, State#state{inflight = maps:remove(Ref, Inflight)}};
|
||||||
_ ->
|
_ ->
|
||||||
{noreply, State}
|
{noreply, State}
|
||||||
@ -171,14 +159,14 @@ handle_info(Info, State) ->
|
|||||||
logger:warning("[ssl_channel] get a unknown message: ~p, state: ~p", [Info, State]),
|
logger:warning("[ssl_channel] get a unknown message: ~p, state: ~p", [Info, State]),
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
terminate(Reason, #state{}) ->
|
terminate(Reason, #state{inflight = Inflight}) ->
|
||||||
|
maps:foreach(fun(Ref, CommandInfo) -> reply_command_closed(Ref, CommandInfo, Reason) end, Inflight),
|
||||||
logger:warning("[ssl_channel] stop with reason: ~p", [Reason]),
|
logger:warning("[ssl_channel] stop with reason: ~p", [Reason]),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%%%% helper methods
|
%%%% helper methods
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
@ -252,17 +240,7 @@ handle_command_response_frame(Ref, Reply, Inflight, State) when is_reference(Ref
|
|||||||
{noreply, State};
|
{noreply, State};
|
||||||
{#inflight_command{receiver_pid = ReceiverPid, timer_ref = TimerRef}, NInflight} ->
|
{#inflight_command{receiver_pid = ReceiverPid, timer_ref = TimerRef}, NInflight} ->
|
||||||
erlang:cancel_timer(TimerRef),
|
erlang:cancel_timer(TimerRef),
|
||||||
case ReceiverPid of
|
deliver_command_response(ReceiverPid, Ref, Reply),
|
||||||
undefined ->
|
|
||||||
ok;
|
|
||||||
_ when is_pid(ReceiverPid) ->
|
|
||||||
case is_process_alive(ReceiverPid) of
|
|
||||||
true ->
|
|
||||||
ReceiverPid ! {command_reply, Ref, decode_command_response(Reply)};
|
|
||||||
false ->
|
|
||||||
logger:warning("[ws_channel] get command_response: ~p, ref: ~p, but receiver_pid is deaded", [Reply, Ref])
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
{noreply, State#state{inflight = NInflight}}
|
{noreply, State#state{inflight = NInflight}}
|
||||||
end;
|
end;
|
||||||
handle_command_response_frame(Ref, Reply, _Inflight, State) ->
|
handle_command_response_frame(Ref, Reply, _Inflight, State) ->
|
||||||
@ -282,9 +260,38 @@ decode_command_response({container, {ok, Result}}) ->
|
|||||||
{ok, Result};
|
{ok, Result};
|
||||||
decode_command_response({container, {error, Reason}}) ->
|
decode_command_response({container, {error, Reason}}) ->
|
||||||
{error, Reason};
|
{error, Reason};
|
||||||
|
decode_command_response({auth, ok}) ->
|
||||||
|
ok;
|
||||||
|
decode_command_response({auth, {error, Reason}}) ->
|
||||||
|
{error, Reason};
|
||||||
decode_command_response(_Reply) ->
|
decode_command_response(_Reply) ->
|
||||||
{error, invalid_response}.
|
{error, invalid_response}.
|
||||||
|
|
||||||
|
-spec deliver_command_response(undefined | pid(), reference(), tuple()) -> ok.
|
||||||
|
deliver_command_response(undefined, _Ref, _Reply) ->
|
||||||
|
ok;
|
||||||
|
deliver_command_response(ReceiverPid, Ref, Reply) when is_pid(ReceiverPid) ->
|
||||||
|
case is_process_alive(ReceiverPid) of
|
||||||
|
true ->
|
||||||
|
ReceiverPid ! {command_reply, Ref, decode_command_response(Reply)};
|
||||||
|
false ->
|
||||||
|
logger:warning("[ws_channel] get command_response: ~p, ref: ~p, but receiver_pid is deaded", [Reply, Ref])
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec reply_command_timeout(undefined | pid(), reference()) -> ok.
|
||||||
|
reply_command_timeout(ReceiverPid, Ref) when is_pid(ReceiverPid) ->
|
||||||
|
ReceiverPid ! {command_reply, Ref, {error, timeout}},
|
||||||
|
ok;
|
||||||
|
reply_command_timeout(_ReceiverPid, _Ref) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
-spec reply_command_closed(reference(), #inflight_command{}, term()) -> ok.
|
||||||
|
reply_command_closed(Ref, #inflight_command{receiver_pid = ReceiverPid}, Reason) when is_pid(ReceiverPid) ->
|
||||||
|
ReceiverPid ! {command_reply, Ref, {error, {channel_closed, Reason}}},
|
||||||
|
ok;
|
||||||
|
reply_command_closed(_Ref, _CommandInfo, _Reason) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
%% 检测token是否是合法值
|
%% 检测token是否是合法值
|
||||||
-spec auth(Token :: binary(), UUID :: binary(), Timestamp :: integer()) ->
|
-spec auth(Token :: binary(), UUID :: binary(), Timestamp :: integer()) ->
|
||||||
ok | {error, Reason :: binary()}.
|
ok | {error, Reason :: binary()}.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user