From 42b3b8b2fa50b8b79efe8b1a78b42d4a82234be7 Mon Sep 17 00:00:00 2001 From: anlicheng Date: Thu, 15 Jun 2023 14:58:55 +0800 Subject: [PATCH] fix --- .../src/http_handler/http_host_handler.erl | 38 +++++++++---------- apps/iot/src/iot_host.erl | 27 +++++++++---- apps/iot/src/mocker/host_mocker.erl | 11 +++--- docs/host-mqtt-jiaohu.md | 3 +- 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/apps/iot/src/http_handler/http_host_handler.erl b/apps/iot/src/http_handler/http_host_handler.erl index 3e9ea47..411f179 100644 --- a/apps/iot/src/http_handler/http_host_handler.erl +++ b/apps/iot/src/http_handler/http_host_handler.erl @@ -112,29 +112,26 @@ handle_request("POST", "/host/activate", _, #{<<"uuid">> := UUID, <<"auth">> := lager:debug("[host_handler] activate host_id: ~p, failed with reason: ~p", [UUID, Reason]), {ok, 200, iot_util:json_error(400, <<"host not found">>)}; {ok, Pid} when is_pid(Pid) -> - lager:debug("[host_handler] activate host_id: ~p, start", [UUID]), - %% 下发指令 - {ok, Assoc, Aes} = iot_host:make_assoc(Pid), - ReplyTopic = iot_host:upstream_topic(UUID), - Reply = case Auth of - true -> - #{<<"auth">> => true, <<"aes">> => Aes, <<"reply">> => #{<<"topic">> => ReplyTopic, <<"assoc">> => Assoc}}; - false -> - #{<<"auth">> => false, <<"aes">> => <<"">>, <<"reply">> => #{ <<"topic">> => ReplyTopic, <<"assoc">> => Assoc}} - end, - BinReply = jiffy:encode(Reply, [force_utf8]), + case iot_host:has_session(Pid) of + true -> + lager:debug("[host_handler] activate host_id: ~p, start", [UUID]), + {ok, Assoc} = iot_host:make_assoc(Pid), + ReplyTopic = iot_host:upstream_topic(UUID), + Reply = case Auth of + true -> + #{<<"auth">> => true, <<"reply">> => #{<<"topic">> => ReplyTopic, <<"assoc">> => Assoc}}; + false -> + #{<<"auth">> => false, <<"reply">> => #{ <<"topic">> => ReplyTopic, <<"assoc">> => Assoc}} + end, + BinReply = jiffy:encode(Reply, [force_utf8]), - CommandType = 8, - case iot_host:rsa_encode(Pid, CommandType, BinReply) of - {error, Reason} when is_binary(Reason) -> - {ok, 200, iot_util:json_error(401, Reason)}; - {ok, BinCommand} -> + CommandType = 8, Topic = iot_host:downstream_topic(UUID), - case iot_mqtt_publisher:publish(Topic, BinCommand, 2) of + + case iot_mqtt_publisher:publish(Topic, <>, 2) of {ok, Ref} -> receive {ok, Ref, _PacketId} -> - %% 等待主机返回确认消息 receive {host_reply, Assoc, #{<<"code">> := 1}} -> ok = iot_host:activate(Pid, Auth), @@ -151,7 +148,10 @@ handle_request("POST", "/host/activate", _, #{<<"uuid">> := UUID, <<"auth">> := {error, Reason} -> lager:debug("[iot_host] host_id uuid: ~p, publish topic get error: ~p", [UUID, Reason]), {ok, 200, iot_util:json_error(402, <<"发送命令到mqtt服务失败"/utf8>>)} - end + end; + false -> + ok = iot_host:activate(Pid, Auth), + {ok, 200, iot_util:json_data(<<"success">>)} end end; diff --git a/apps/iot/src/iot_host.erl b/apps/iot/src/iot_host.erl index 3f36fc0..063792c 100644 --- a/apps/iot/src/iot_host.erl +++ b/apps/iot/src/iot_host.erl @@ -19,6 +19,7 @@ %% API -export([start_link/2, get_name/1, get_pid/1, handle/2, reload/1, activate/2]). -export([get_metric/1, aes_encode/3, downstream_topic/1, upstream_topic/1, get_aes/1, make_assoc/1, rsa_encode/3]). +-export([has_session/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -77,11 +78,6 @@ downstream_topic(UUID) when is_binary(UUID) -> upstream_topic(UUID) when is_binary(UUID) -> <<"host/upstream/", UUID/binary>>. --spec rsa_encode(Pid :: pid(), CommandType :: integer(), PlainText :: binary()) -> - {ok, EncText :: binary()} | {error, Reason :: binary()}. -rsa_encode(Pid, CommandType, PlainText) when is_pid(Pid), is_integer(CommandType), is_binary(PlainText) -> - gen_server:call(Pid, {rsa_encode, CommandType, PlainText}). - %% 处理消息 -spec handle(Pid :: pid(), Payload :: binary() | map()) -> no_return(). handle(Pid, Payload) when is_pid(Pid), is_binary(Payload); is_map(Payload) -> @@ -96,7 +92,7 @@ reload(Pid) when is_pid(Pid) -> get_aes(Pid) when is_pid(Pid) -> gen_server:call(Pid, get_aes). --spec make_assoc(Pid :: pid()) -> {ok, Assoc :: binary(), Aes :: binary()}. +-spec make_assoc(Pid :: pid()) -> {ok, Assoc :: binary()}. make_assoc(Pid) when is_pid(Pid) -> gen_server:call(Pid, {make_assoc, self()}). @@ -109,6 +105,16 @@ activate(Pid, Auth) when is_pid(Pid), is_boolean(Auth) -> get_metric(Pid) when is_pid(Pid) -> gen_server:call(Pid, get_metric). +-spec has_session(Pid :: pid()) -> boolean(). +has_session(Pid) when is_pid(Pid) -> + gen_server:call(Pid, has_session). + +%% 基于rsa加密的指令都是不需要会话存在的 +-spec rsa_encode(Pid :: pid(), CommandType :: integer(), PlainText :: binary()) -> + {ok, EncText :: binary()} | {error, Reason :: binary()}. +rsa_encode(Pid, CommandType, PlainText) when is_pid(Pid), is_integer(CommandType), is_binary(PlainText) -> + gen_server:call(Pid, {rsa_encode, CommandType, PlainText}). + -spec aes_encode(Pid :: pid(), CommandType :: integer(), Params :: binary()) -> {ok, Command :: binary()} | {error, Reason :: any()}. aes_encode(Pid, CommandType, Params) when is_pid(Pid), is_integer(CommandType), is_binary(Params) -> @@ -160,7 +166,12 @@ handle_call(get_metric, _From, State) -> handle_call(get_aes, _From, State = #state{aes = Aes}) -> {reply, {ok, Aes}, State}; +%% 获取当前是否存在会话 +handle_call(has_session, _From, State = #state{has_session = HasSession}) -> + {reply, HasSession, State}; + %% 实现rsa加密 +%% 基于rsa加密的指令都是不需要会话存在的 handle_call({rsa_encode, _, _}, _From, State = #state{has_session = false}) -> {reply, {error, <<"会话未建立,发送命令失败"/utf8>>}, State}; handle_call({rsa_encode, CommandType, PlainText}, _From, State = #state{pub_key = PubKey}) -> @@ -168,11 +179,11 @@ handle_call({rsa_encode, CommandType, PlainText}, _From, State = #state{pub_key {reply, {ok, <>}, State}; -handle_call({make_assoc, ReceivePid}, _From, State = #state{uuid = UUID, increment_id = IncrementId, assoc_map = AssocMap, aes = Aes}) -> +handle_call({make_assoc, ReceivePid}, _From, State = #state{uuid = UUID, increment_id = IncrementId, assoc_map = AssocMap}) -> BinIncrementId = erlang:integer_to_binary(IncrementId), Assoc = <>, - {reply, {ok, Assoc, Aes}, State#state{assoc_map = maps:put(Assoc, ReceivePid, AssocMap), increment_id = IncrementId + 1}}; + {reply, {ok, Assoc}, State#state{assoc_map = maps:put(Assoc, ReceivePid, AssocMap), increment_id = IncrementId + 1}}; %% 重新加载主机信息 handle_call(reload, _From, State = #state{uuid = UUID}) -> diff --git a/apps/iot/src/mocker/host_mocker.erl b/apps/iot/src/mocker/host_mocker.erl index 93df953..b101147 100644 --- a/apps/iot/src/mocker/host_mocker.erl +++ b/apps/iot/src/mocker/host_mocker.erl @@ -200,11 +200,10 @@ handle_info({publish, #{payload := Payload, qos := Qos, topic := FromTopic}}, lager:debug("[host_mocker] auth failed") end; - %% 8 是通过rsa加密的数据,里面保存了aes;后续的所有通讯都是通过aes加密的 - <<8:8, Command0/binary>> -> - Command = iot_cipher_rsa:decode(Command0, PrivateKey), + %% t = 8采用明文消息 + <<8:8, Command/binary>> -> case jiffy:decode(Command, [return_maps]) of - #{<<"aes">> := Aes, <<"auth">> := true, <<"reply">> := #{<<"topic">> := Topic, <<"assoc">> := Assoc}} -> + #{<<"auth">> := true, <<"reply">> := #{<<"topic">> := Topic, <<"assoc">> := Assoc}} -> Msg = jiffy:encode(#{ <<"code">> => 1, <<"message">> => "", @@ -219,9 +218,9 @@ handle_info({publish, #{payload := Payload, qos := Qos, topic := FromTopic}}, lager:debug("[host_mocker] send reply failed, reason: ~p", [Reason]) end, - {noreply, State#state{aes = Aes}}; + {noreply, State}; - #{<<"aes">> := Aes, <<"auth">> := false, <<"reply">> := #{<<"topic">> := Topic, <<"assoc">> := Assoc}} -> + #{<<"auth">> := false, <<"reply">> := #{<<"topic">> := Topic, <<"assoc">> := Assoc}} -> Msg = jiffy:encode(#{ <<"code">> => 1, <<"message">> => "", diff --git a/docs/host-mqtt-jiaohu.md b/docs/host-mqtt-jiaohu.md index cc1c954..d7261b6 100644 --- a/docs/host-mqtt-jiaohu.md +++ b/docs/host-mqtt-jiaohu.md @@ -74,11 +74,10 @@ t = 8 ```json -// 数据采用之前协商的aes加密 +// 数据采用明文传输,主机在收到通知后,需要通过create_session操作重新协商aes { "auth": true/false, // true表示授权,此时aes的值不为空;false表示取消授权 - "aes": "", "reply": { "topic": "", // 主机端操作成功后需要回写的topic名称 "assoc": "" // 关联的信息,回写的时候需要带上