diff --git a/src/host/iot_host.erl b/src/host/iot_host.erl index 78bc763..3e987f0 100644 --- a/src/host/iot_host.erl +++ b/src/host/iot_host.erl @@ -95,46 +95,47 @@ attach_channel(Pid, ChannelPid) when is_pid(Pid), is_pid(ChannelPid) -> -spec get_containers(Pid :: pid()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. get_containers(Pid) when is_pid(Pid) -> - gen_statem:call(Pid, {jsonrpc_call, self(), {<<"get_containers">>, #{}}}). + gen_statem:call(Pid, {jsonrpc_call, self(), {<<"get_containers">>, <<"{}">>}}). -spec config_container(Pid :: pid(), ContainerName :: binary(), ConfigJson :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. config_container(Pid, ContainerName, ConfigJson) when is_pid(Pid), is_binary(ContainerName), is_binary(ConfigJson) -> - Params = #{<<"container_name">> => ContainerName, <<"config">> => ConfigJson}, + Params = jiffy:encode(#{ + <<"container_name">> => ContainerName, + <<"config">> => ConfigJson + }, [force_utf8]), gen_statem:call(Pid, {jsonrpc_call, self(), {<<"config_container">>, Params}}). --spec deploy_container(Pid :: pid(), TaskId :: integer(), Config :: map()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. -deploy_container(Pid, TaskId, Config) when is_pid(Pid), is_integer(TaskId), is_map(Config) -> - Params = #{<<"task_id">> => TaskId, <<"config">> => Config}, +-spec deploy_container(Pid :: pid(), TaskId :: integer(), Params :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. +deploy_container(Pid, TaskId, Params) when is_pid(Pid), is_integer(TaskId), is_binary(Params) -> gen_statem:call(Pid, {jsonrpc_call, self(), {<<"deploy">>, Params}}). -spec start_container(Pid :: pid(), ContainerName :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. start_container(Pid, ContainerName) when is_pid(Pid), is_binary(ContainerName) -> - Params = #{<<"container_name">> => ContainerName}, + Params = jiffy:encode(#{<<"container_name">> => ContainerName}, [force_utf8]), gen_statem:call(Pid, {jsonrpc_call, self(), {<<"start_container">>, Params}}). -spec stop_container(Pid :: pid(), ContainerName :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. stop_container(Pid, ContainerName) when is_pid(Pid), is_binary(ContainerName) -> - Params = #{<<"container_name">> => ContainerName}, + Params = jiffy:encode(#{<<"container_name">> => ContainerName}, [force_utf8]), gen_statem:call(Pid, {jsonrpc_call, self(), {<<"stop_container">>, Params}}). -spec kill_container(Pid :: pid(), ContainerName :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. kill_container(Pid, ContainerName) when is_pid(Pid), is_binary(ContainerName) -> - Params = #{<<"container_name">> => ContainerName}, + Params = jiffy:encode(#{<<"container_name">> => ContainerName}, [force_utf8]), gen_statem:call(Pid, {jsonrpc_call, self(), {<<"kill_container">>, Params}}). -spec remove_container(Pid :: pid(), ContainerName :: binary()) -> {ok, Ref :: reference()} | {error, Reason :: any()}. remove_container(Pid, ContainerName) when is_pid(Pid), is_binary(ContainerName) -> - Params = #{<<"container_name">> => ContainerName}, + Params = jiffy:encode(#{<<"container_name">> => ContainerName}, [force_utf8]), gen_statem:call(Pid, {jsonrpc_call, self(), {<<"remove_container">>, Params}}). -spec await_reply(Pid :: pid(), Ref :: reference(), Timeout :: integer()) -> {ok, Result :: binary()} | {error, Reason :: binary()}. await_reply(Pid, Ref, Timeout) when is_pid(Pid), is_reference(Ref), is_integer(Timeout) -> receive {jsonrpc_reply, Ref, #'JsonRpcReply'{result = ResultBin, error = <<>>}} -> - {ok, erlang:binary_to_term(iolist_to_binary(ResultBin))}; + {ok, iolist_to_binary(ResultBin)}; {jsonrpc_reply, Ref, #'JsonRpcReply'{result = <<>>, error = ErrorBin}} -> - #{<<"message">> := Message} = erlang:binary_to_term(iolist_to_binary(ErrorBin)), - {error, Message} + {error, iolist_to_binary(ErrorBin)} after Timeout -> ok = gen_statem:call(Pid, {cancel_jsonrpc_call, Ref}), flush_reply(Ref), diff --git a/src/transport/http/container_handler.erl b/src/transport/http/container_handler.erl index 1ea7980..0c133e1 100644 --- a/src/transport/http/container_handler.erl +++ b/src/transport/http/container_handler.erl @@ -25,9 +25,9 @@ handle_request("GET", "/container/get_all", #{<<"uuid">> := UUID}, _) when is_bi {ok, Ref} -> case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; + {ok, 200, rpc_success_response(Result)}; {error, Reason} -> - {ok, 200, iot_util:json_error(-1, Reason)} + {ok, 200, rpc_error_response(-1, Reason)} end; {error, Reason} when is_binary(Reason) -> {ok, 200, iot_util:json_error(-1, Reason)} @@ -50,9 +50,9 @@ handle_request("POST", "/container/push_config", _, {ok, Ref} -> case iot_host:await_reply(Pid, Ref, Timeout) of {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; + {ok, 200, rpc_success_response(Result)}; {error, Reason} -> - {ok, 200, iot_util:json_error(-1, Reason)} + {ok, 200, rpc_error_response(-1, Reason)} end; {error, Reason} when is_binary(Reason) -> {ok, 200, iot_util:json_error(-1, Reason)} @@ -69,13 +69,17 @@ handle_request("POST", "/container/deploy", _, #{<<"uuid">> := UUID, <<"task_id" undefined -> {ok, 200, iot_util:json_error(404, <<"host not found">>)}; Pid when is_pid(Pid) -> - case iot_host:deploy_container(Pid, TaskId, Config) of + Params = jiffy:encode(#{ + <<"task_id">> => TaskId, + <<"config">> => Config + }, [force_utf8]), + case iot_host:deploy_container(Pid, TaskId, Params) of {ok, Ref} -> case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; + {ok, 200, rpc_success_response(Result)}; {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} + {ok, 200, rpc_error_response(400, Reason)} end; {error, Reason} when is_binary(Reason) -> {ok, 200, iot_util:json_error(400, Reason)} @@ -96,9 +100,9 @@ handle_request("POST", "/container/start", _, #{<<"uuid">> := UUID, <<"container {ok, Ref} -> case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; + {ok, 200, rpc_success_response(Result)}; {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} + {ok, 200, rpc_error_response(400, Reason)} end; {error, Reason} when is_binary(Reason) -> {ok, 200, iot_util:json_error(400, Reason)} @@ -115,9 +119,9 @@ handle_request("POST", "/container/stop", _, #{<<"uuid">> := UUID, <<"container_ {ok, Ref} -> case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; + {ok, 200, rpc_success_response(Result)}; {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} + {ok, 200, rpc_error_response(400, Reason)} end; {error, Reason} when is_binary(Reason) -> {ok, 200, iot_util:json_error(400, Reason)} @@ -133,9 +137,9 @@ handle_request("POST", "/container/kill", _, #{<<"uuid">> := UUID, <<"container_ {ok, Ref} -> case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; + {ok, 200, rpc_success_response(Result)}; {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} + {ok, 200, rpc_error_response(400, Reason)} end; {error, Reason} when is_binary(Reason) -> {ok, 200, iot_util:json_error(400, Reason)} @@ -152,9 +156,9 @@ handle_request("POST", "/container/remove", _, #{<<"uuid">> := UUID, <<"containe {ok, Ref} -> case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of {ok, Result} -> - {ok, 200, iot_util:json_data(Result)}; + {ok, 200, rpc_success_response(Result)}; {error, Reason} -> - {ok, 200, iot_util:json_error(400, Reason)} + {ok, 200, rpc_error_response(400, Reason)} end; {error, Reason} when is_binary(Reason) -> {ok, 200, iot_util:json_error(400, Reason)} @@ -307,3 +311,31 @@ check_type(Value, boolean) -> is_boolean(Value); check_type(_, _) -> false. + +rpc_success_response(Result) when is_binary(Result) -> + case decode_json_bytes(Result) of + {ok, Data} -> + iot_util:json_data(Data); + error -> + iot_util:json_data(Result) + end. + +rpc_error_response(Code, Reason) when is_integer(Code), is_binary(Reason) -> + case decode_json_bytes(Reason) of + {ok, #{<<"message">> := Message}} when is_binary(Message) -> + iot_util:json_error(Code, Message); + {ok, Message} when is_binary(Message) -> + iot_util:json_error(Code, Message); + _ -> + iot_util:json_error(Code, Reason) + end. + +decode_json_bytes(Data) when is_binary(Data) -> + case catch jiffy:decode(Data, [return_maps]) of + {'EXIT', _} -> + error; + {error, _} -> + error; + Decoded -> + {ok, Decoded} + end. diff --git a/src/transport/tcp/tcp_channel.erl b/src/transport/tcp/tcp_channel.erl index 71609ec..c77dd1c 100644 --- a/src/transport/tcp/tcp_channel.erl +++ b/src/transport/tcp/tcp_channel.erl @@ -53,8 +53,8 @@ command(Pid, CommandType, Command) when is_pid(Pid), is_integer(CommandType), is gen_server:cast(Pid, {command, CommandType, Command}). %% 向通道中写入消息 --spec jsonrpc_call(Pid :: pid(), ReceiverPid :: pid(), Request :: {Method :: binary(), Params :: any()}) -> Ref :: reference(). -jsonrpc_call(Pid, ReceiverPid, Request = {Method, _Params}) when is_pid(Pid), is_pid(ReceiverPid), is_binary(Method) -> +-spec jsonrpc_call(Pid :: pid(), ReceiverPid :: pid(), Request :: {Method :: binary(), Params :: binary()}) -> Ref :: reference(). +jsonrpc_call(Pid, ReceiverPid, Request = {Method, Params}) when is_pid(Pid), is_pid(ReceiverPid), is_binary(Method), is_binary(Params) -> Ref = make_ref(), gen_server:cast(Pid, {jsonrpc_call, ReceiverPid, Ref, Request}), Ref. @@ -114,7 +114,7 @@ handle_cast({jsonrpc_call, ReceiverPid, Ref, {Method, Params}}, State = #state{t {ok, NPacketId, NextPacketId} -> Encoded = message_pb:encode_msg(#'JsonRpcRequest'{ method = Method, - params = erlang:term_to_binary(Params) + params = Params }), EncRequest = <>,