初步完善传输层
This commit is contained in:
parent
5b9c4aa06d
commit
8fd58750aa
@ -8,13 +8,6 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-author("anlicheng").
|
-author("anlicheng").
|
||||||
|
|
||||||
%% efka主动发起的消息体类型, 消息大类
|
|
||||||
-define(PACKET_REQUEST, 16#01).
|
|
||||||
-define(PACKET_RESPONSE, 16#02).
|
|
||||||
|
|
||||||
%% efka主动发起不需要返回的数据
|
|
||||||
-define(PACKET_CAST, 16#03).
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%%%% 二级分类定义
|
%%%% 二级分类定义
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
@ -24,11 +17,9 @@
|
|||||||
-define(MESSAGE_AUTH_REPLY, 16#02).
|
-define(MESSAGE_AUTH_REPLY, 16#02).
|
||||||
|
|
||||||
-define(MESSAGE_COMMAND, 16#03).
|
-define(MESSAGE_COMMAND, 16#03).
|
||||||
-define(MESSAGE_DEPLOY, 16#04).
|
|
||||||
-define(MESSAGE_PUB, 16#05).
|
-define(MESSAGE_PUB, 16#05).
|
||||||
|
|
||||||
-define(MESSAGE_DATA, 16#06).
|
-define(MESSAGE_DATA, 16#06).
|
||||||
-define(MESSAGE_EVENT, 16#07).
|
|
||||||
|
|
||||||
%% efka主动上报的event-stream流, 单向消息,主要是: docker-create的实时处理逻辑上报
|
%% efka主动上报的event-stream流, 单向消息,主要是: docker-create的实时处理逻辑上报
|
||||||
-define(MESSAGE_EVENT_STREAM, 16#08).
|
-define(MESSAGE_EVENT_STREAM, 16#08).
|
||||||
@ -39,48 +30,3 @@
|
|||||||
%%%% 命令类型子分类, 不需要返回值
|
%%%% 命令类型子分类, 不需要返回值
|
||||||
%% 授权
|
%% 授权
|
||||||
-define(COMMAND_AUTH, 16#08).
|
-define(COMMAND_AUTH, 16#08).
|
||||||
|
|
||||||
-record(auth_request, {
|
|
||||||
uuid :: binary(),
|
|
||||||
username :: binary(),
|
|
||||||
salt :: binary(),
|
|
||||||
token :: binary(),
|
|
||||||
timestamp :: integer()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(auth_reply, {
|
|
||||||
code :: integer(),
|
|
||||||
payload :: binary()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(pub, {
|
|
||||||
topic :: binary(),
|
|
||||||
qos = 0 :: integer(),
|
|
||||||
content :: binary()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(command, {
|
|
||||||
command_type :: integer(),
|
|
||||||
command :: binary()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(jsonrpc_request, {
|
|
||||||
method :: binary(),
|
|
||||||
params = <<>> :: any()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(jsonrpc_reply, {
|
|
||||||
result :: any() | undefined,
|
|
||||||
error :: any() | undefined
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(data, {
|
|
||||||
route_key :: binary(),
|
|
||||||
metric :: binary()
|
|
||||||
}).
|
|
||||||
|
|
||||||
-record(task_event_stream, {
|
|
||||||
task_id :: integer(),
|
|
||||||
type :: binary(),
|
|
||||||
stream :: binary()
|
|
||||||
}).
|
|
||||||
296
include/message_pb.hrl
Normal file
296
include/message_pb.hrl
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
%% -*- coding: utf-8 -*-
|
||||||
|
%% Automatically generated, do not edit
|
||||||
|
%% Generated by gpb_compile version 4.21.7
|
||||||
|
|
||||||
|
-ifndef(message_pb).
|
||||||
|
-define(message_pb, true).
|
||||||
|
|
||||||
|
-define(message_pb_gpb_version, "4.21.7").
|
||||||
|
|
||||||
|
|
||||||
|
-ifndef('REQUESTFRAME_PB_H').
|
||||||
|
-define('REQUESTFRAME_PB_H', true).
|
||||||
|
-record('RequestFrame',
|
||||||
|
{packet_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||||
|
body :: {auth_request, message_pb:'AuthRequest'()} | {rpc_request, message_pb:'RpcRequest'()} | {container_request, message_pb:'ContainerRequest'()} | undefined % oneof
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('RESPONSEFRAME_PB_H').
|
||||||
|
-define('RESPONSEFRAME_PB_H', true).
|
||||||
|
-record('ResponseFrame',
|
||||||
|
{packet_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||||
|
body :: {auth_reply, message_pb:'AuthReply'()} | {rpc_reply, message_pb:'RpcReply'()} | undefined % oneof
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CASTFRAME_PB_H').
|
||||||
|
-define('CASTFRAME_PB_H', true).
|
||||||
|
-record('CastFrame',
|
||||||
|
{body :: {pub, message_pb:'Pub'()} | {command, message_pb:'Command'()} | {data, message_pb:'Data'()} | {event_stream, message_pb:'TaskEventStream'()} | undefined % oneof
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERREF_PB_H').
|
||||||
|
-define('CONTAINERREF_PB_H', true).
|
||||||
|
-record('ContainerRef',
|
||||||
|
{id = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
|
name = <<>> :: unicode:chardata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERREQUEST.LIST_PB_H').
|
||||||
|
-define('CONTAINERREQUEST.LIST_PB_H', true).
|
||||||
|
-record('ContainerRequest.List',
|
||||||
|
{all = false :: boolean() | 0 | 1 | undefined % = 1, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERREQUEST.DEPLOY_PB_H').
|
||||||
|
-define('CONTAINERREQUEST.DEPLOY_PB_H', true).
|
||||||
|
-record('ContainerRequest.Deploy',
|
||||||
|
{task_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||||
|
params = undefined :: message_pb:'ContainerDeployParams'() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERREQUEST.START_PB_H').
|
||||||
|
-define('CONTAINERREQUEST.START_PB_H', true).
|
||||||
|
-record('ContainerRequest.Start',
|
||||||
|
{target = undefined :: message_pb:'ContainerRef'() | undefined % = 1, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERREQUEST.STOP_PB_H').
|
||||||
|
-define('CONTAINERREQUEST.STOP_PB_H', true).
|
||||||
|
-record('ContainerRequest.Stop',
|
||||||
|
{target = undefined :: message_pb:'ContainerRef'() | undefined, % = 1, optional
|
||||||
|
timeout_seconds = 0 :: non_neg_integer() | undefined % = 2, optional, 32 bits
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERREQUEST.KILL_PB_H').
|
||||||
|
-define('CONTAINERREQUEST.KILL_PB_H', true).
|
||||||
|
-record('ContainerRequest.Kill',
|
||||||
|
{target = undefined :: message_pb:'ContainerRef'() | undefined, % = 1, optional
|
||||||
|
signal = <<>> :: unicode:chardata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERREQUEST.REMOVE_PB_H').
|
||||||
|
-define('CONTAINERREQUEST.REMOVE_PB_H', true).
|
||||||
|
-record('ContainerRequest.Remove',
|
||||||
|
{target = undefined :: message_pb:'ContainerRef'() | undefined, % = 1, optional
|
||||||
|
force = false :: boolean() | 0 | 1 | undefined, % = 2, optional
|
||||||
|
remove_volumes = false :: boolean() | 0 | 1 | undefined % = 3, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERREQUEST.CONFIG_PB_H').
|
||||||
|
-define('CONTAINERREQUEST.CONFIG_PB_H', true).
|
||||||
|
-record('ContainerRequest.Config',
|
||||||
|
{target = undefined :: message_pb:'ContainerRef'() | undefined, % = 1, optional
|
||||||
|
config = <<>> :: iodata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERREQUEST_PB_H').
|
||||||
|
-define('CONTAINERREQUEST_PB_H', true).
|
||||||
|
-record('ContainerRequest',
|
||||||
|
{action :: {list, message_pb:'ContainerRequest.List'()} | {deploy, message_pb:'ContainerRequest.Deploy'()} | {start, message_pb:'ContainerRequest.Start'()} | {stop, message_pb:'ContainerRequest.Stop'()} | {kill, message_pb:'ContainerRequest.Kill'()} | {remove, message_pb:'ContainerRequest.Remove'()} | {config, message_pb:'ContainerRequest.Config'()} | undefined % oneof
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERDEPLOYPARAMS_PB_H').
|
||||||
|
-define('CONTAINERDEPLOYPARAMS_PB_H', true).
|
||||||
|
-record('ContainerDeployParams',
|
||||||
|
{container_name = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
|
container_dir = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
||||||
|
spec = undefined :: message_pb:'ContainerSpec'() | undefined % = 3, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('CONTAINERSPEC_PB_H').
|
||||||
|
-define('CONTAINERSPEC_PB_H', true).
|
||||||
|
-record('ContainerSpec',
|
||||||
|
{image = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
|
command = [] :: [unicode:chardata()] | undefined, % = 2, repeated
|
||||||
|
entrypoint = [] :: [unicode:chardata()] | undefined, % = 3, repeated
|
||||||
|
env = [] :: [unicode:chardata()] | undefined, % = 4, repeated
|
||||||
|
labels = [] :: [{unicode:chardata(), unicode:chardata()}] | undefined, % = 5
|
||||||
|
volumes = [] :: [message_pb:'VolumeBind'()] | undefined, % = 6, repeated
|
||||||
|
user = <<>> :: unicode:chardata() | undefined, % = 7, optional
|
||||||
|
working_dir = <<>> :: unicode:chardata() | undefined, % = 8, optional
|
||||||
|
hostname = <<>> :: unicode:chardata() | undefined, % = 9, optional
|
||||||
|
expose = [] :: [message_pb:'PortExpose'()] | undefined, % = 10, repeated
|
||||||
|
networks = [] :: [unicode:chardata()] | undefined, % = 11, repeated
|
||||||
|
network_mode = <<>> :: unicode:chardata() | undefined, % = 12, optional
|
||||||
|
healthcheck = undefined :: message_pb:'Healthcheck'() | undefined, % = 13, optional
|
||||||
|
restart = undefined :: message_pb:'RestartPolicy'() | undefined, % = 14, optional
|
||||||
|
privileged = false :: boolean() | 0 | 1 | undefined, % = 15, optional
|
||||||
|
cap_add = [] :: [unicode:chardata()] | undefined, % = 16, repeated
|
||||||
|
cap_drop = [] :: [unicode:chardata()] | undefined, % = 17, repeated
|
||||||
|
devices = [] :: [message_pb:'DeviceMapping'()] | undefined, % = 18, repeated
|
||||||
|
resources = undefined :: message_pb:'ResourceLimits'() | undefined, % = 19, optional
|
||||||
|
ulimits = [] :: [message_pb:'Ulimit'()] | undefined, % = 20, repeated
|
||||||
|
tmpfs = [] :: [message_pb:'TmpfsMount'()] | undefined, % = 21, repeated
|
||||||
|
sysctls = [] :: [{unicode:chardata(), unicode:chardata()}] | undefined, % = 22
|
||||||
|
extra_hosts = [] :: [unicode:chardata()] | undefined % = 23, repeated
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('VOLUMEBIND_PB_H').
|
||||||
|
-define('VOLUMEBIND_PB_H', true).
|
||||||
|
-record('VolumeBind',
|
||||||
|
{host_path = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
|
container_path = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
||||||
|
read_only = false :: boolean() | 0 | 1 | undefined % = 3, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('PORTEXPOSE_PB_H').
|
||||||
|
-define('PORTEXPOSE_PB_H', true).
|
||||||
|
-record('PortExpose',
|
||||||
|
{container_port = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||||
|
protocol = <<>> :: unicode:chardata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('HEALTHCHECK_PB_H').
|
||||||
|
-define('HEALTHCHECK_PB_H', true).
|
||||||
|
-record('Healthcheck',
|
||||||
|
{test = [] :: [unicode:chardata()] | undefined, % = 1, repeated
|
||||||
|
interval_ns = 0 :: non_neg_integer() | undefined, % = 2, optional, 64 bits
|
||||||
|
timeout_ns = 0 :: non_neg_integer() | undefined, % = 3, optional, 64 bits
|
||||||
|
retries = 0 :: non_neg_integer() | undefined % = 4, optional, 32 bits
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('RESTARTPOLICY_PB_H').
|
||||||
|
-define('RESTARTPOLICY_PB_H', true).
|
||||||
|
-record('RestartPolicy',
|
||||||
|
{name = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
|
maximum_retry_count = 0 :: non_neg_integer() | undefined % = 2, optional, 32 bits
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('DEVICEMAPPING_PB_H').
|
||||||
|
-define('DEVICEMAPPING_PB_H', true).
|
||||||
|
-record('DeviceMapping',
|
||||||
|
{host_path = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
|
container_path = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
||||||
|
cgroup_permissions = <<>> :: unicode:chardata() | undefined % = 3, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('RESOURCELIMITS_PB_H').
|
||||||
|
-define('RESOURCELIMITS_PB_H', true).
|
||||||
|
-record('ResourceLimits',
|
||||||
|
{memory_bytes = 0 :: non_neg_integer() | undefined, % = 1, optional, 64 bits
|
||||||
|
memory_reservation_bytes = 0 :: non_neg_integer() | undefined, % = 2, optional, 64 bits
|
||||||
|
nano_cpus = 0 :: non_neg_integer() | undefined, % = 3, optional, 64 bits
|
||||||
|
cpu_shares = 0 :: non_neg_integer() | undefined % = 4, optional, 64 bits
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('ULIMIT_PB_H').
|
||||||
|
-define('ULIMIT_PB_H', true).
|
||||||
|
-record('Ulimit',
|
||||||
|
{name = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
|
soft = 0 :: non_neg_integer() | undefined, % = 2, optional, 64 bits
|
||||||
|
hard = 0 :: non_neg_integer() | undefined % = 3, optional, 64 bits
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('TMPFSMOUNT_PB_H').
|
||||||
|
-define('TMPFSMOUNT_PB_H', true).
|
||||||
|
-record('TmpfsMount',
|
||||||
|
{path = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||||
|
options = <<>> :: unicode:chardata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('AUTHREQUEST_PB_H').
|
||||||
|
-define('AUTHREQUEST_PB_H', true).
|
||||||
|
-record('AuthRequest',
|
||||||
|
{uuid = <<>> :: iodata() | undefined, % = 1, optional
|
||||||
|
username = <<>> :: iodata() | undefined, % = 2, optional
|
||||||
|
salt = <<>> :: iodata() | undefined, % = 3, optional
|
||||||
|
token = <<>> :: iodata() | undefined, % = 4, optional
|
||||||
|
timestamp = 0 :: integer() | undefined % = 5, optional, 32 bits
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('AUTHREPLY_PB_H').
|
||||||
|
-define('AUTHREPLY_PB_H', true).
|
||||||
|
-record('AuthReply',
|
||||||
|
{code = 0 :: integer() | undefined, % = 1, optional, 32 bits
|
||||||
|
payload = <<>> :: iodata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('PUB_PB_H').
|
||||||
|
-define('PUB_PB_H', true).
|
||||||
|
-record('Pub',
|
||||||
|
{topic = <<>> :: iodata() | undefined, % = 1, optional
|
||||||
|
qos = 0 :: integer() | undefined, % = 2, optional, 32 bits
|
||||||
|
content = <<>> :: iodata() | undefined % = 3, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('COMMAND_PB_H').
|
||||||
|
-define('COMMAND_PB_H', true).
|
||||||
|
-record('Command',
|
||||||
|
{command_type = 0 :: integer() | undefined, % = 1, optional, 32 bits
|
||||||
|
command = <<>> :: iodata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('RPCREQUEST_PB_H').
|
||||||
|
-define('RPCREQUEST_PB_H', true).
|
||||||
|
-record('RpcRequest',
|
||||||
|
{method = <<>> :: iodata() | undefined, % = 1, optional
|
||||||
|
params = <<>> :: iodata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('RPCREPLY.RPCRESULT_PB_H').
|
||||||
|
-define('RPCREPLY.RPCRESULT_PB_H', true).
|
||||||
|
-record('RpcReply.RpcResult',
|
||||||
|
{data = <<>> :: iodata() | undefined % = 1, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('RPCREPLY.RPCERROR_PB_H').
|
||||||
|
-define('RPCREPLY.RPCERROR_PB_H', true).
|
||||||
|
-record('RpcReply.RpcError',
|
||||||
|
{code = 0 :: integer() | undefined, % = 1, optional, 32 bits
|
||||||
|
message = <<>> :: unicode:chardata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('RPCREPLY_PB_H').
|
||||||
|
-define('RPCREPLY_PB_H', true).
|
||||||
|
-record('RpcReply',
|
||||||
|
{reply :: {result, message_pb:'RpcReply.RpcResult'()} | {error, message_pb:'RpcReply.RpcError'()} | undefined % oneof
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('DATA_PB_H').
|
||||||
|
-define('DATA_PB_H', true).
|
||||||
|
-record('Data',
|
||||||
|
{route_key = <<>> :: iodata() | undefined, % = 1, optional
|
||||||
|
metric = <<>> :: iodata() | undefined % = 2, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-ifndef('TASKEVENTSTREAM_PB_H').
|
||||||
|
-define('TASKEVENTSTREAM_PB_H', true).
|
||||||
|
-record('TaskEventStream',
|
||||||
|
{task_id = 0 :: integer() | undefined, % = 1, optional, 32 bits
|
||||||
|
type = <<>> :: iodata() | undefined, % = 2, optional
|
||||||
|
stream = <<>> :: iodata() | undefined % = 3, optional
|
||||||
|
}).
|
||||||
|
-endif.
|
||||||
|
|
||||||
|
-endif.
|
||||||
20
include/protocol.hrl
Normal file
20
include/protocol.hrl
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @author anlicheng
|
||||||
|
%%% @copyright (C) 2025, <COMPANY>
|
||||||
|
%%% @doc
|
||||||
|
%%% 传输层协议常量定义
|
||||||
|
%%% @end
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-author("anlicheng").
|
||||||
|
|
||||||
|
%% 一级帧类型
|
||||||
|
%% REQUEST: 需要响应的请求帧
|
||||||
|
%% RESPONSE: 对 REQUEST 的响应帧
|
||||||
|
%% CAST: 单向消息帧,不需要响应
|
||||||
|
-define(FRAME_REQUEST, 16#01).
|
||||||
|
-define(FRAME_RESPONSE, 16#02).
|
||||||
|
-define(FRAME_CAST, 16#03).
|
||||||
|
|
||||||
|
%%%% 命令类型子分类, 不需要返回值
|
||||||
|
%% 授权
|
||||||
|
-define(COMMAND_AUTH, 16#08).
|
||||||
@ -88,36 +88,30 @@ callback_mode() ->
|
|||||||
|
|
||||||
%% 异步发送数据, 连接存在时候直接发送;否则缓存到mnesia
|
%% 异步发送数据, 连接存在时候直接发送;否则缓存到mnesia
|
||||||
handle_event(cast, {metric_data, RouteKey, Metric}, ?STATE_ACTIVATED, State = #state{transport_pid = TransportPid}) ->
|
handle_event(cast, {metric_data, RouteKey, Metric}, ?STATE_ACTIVATED, State = #state{transport_pid = TransportPid}) ->
|
||||||
Packet = message_codec:encode(?MESSAGE_DATA, #'Data'{
|
Packet = message_pb:encode_msg(#'CastFrame'{
|
||||||
route_key = RouteKey,
|
body = {data, #'Data'{route_key = RouteKey, metric = Metric}}
|
||||||
metric = Metric
|
|
||||||
}),
|
}),
|
||||||
efka_transport:send(TransportPid, Packet),
|
efka_transport:send(TransportPid, Packet),
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
handle_event(cast, {metric_data, RouteKey, Metric}, _, State) ->
|
handle_event(cast, {metric_data, RouteKey, Metric}, _, State) ->
|
||||||
Packet = message_codec:encode(?MESSAGE_DATA, #'Data'{
|
Packet = message_pb:encode_msg(#'CastFrame'{
|
||||||
route_key = RouteKey,
|
body = {data, #'Data'{route_key = RouteKey, metric = Metric}}
|
||||||
metric = Metric
|
|
||||||
}),
|
}),
|
||||||
ok = cache_model:insert(Packet),
|
ok = cache_model:insert(Packet),
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
handle_event(cast, {task_event_stream, TaskId, Type, Stream}, ?STATE_ACTIVATED, State = #state{transport_pid = TransportPid}) ->
|
handle_event(cast, {task_event_stream, TaskId, Type, Stream}, ?STATE_ACTIVATED, State = #state{transport_pid = TransportPid}) ->
|
||||||
logger:debug("[efka_remote_agent] event_stream task_id: ~p, stream: ~ts", [TaskId, Stream]),
|
logger:debug("[efka_remote_agent] event_stream task_id: ~p, stream: ~ts", [TaskId, Stream]),
|
||||||
EventPacket = message_codec:encode(?MESSAGE_EVENT_STREAM, #'TaskEventStream'{
|
EventPacket = message_pb:encode_msg(#'CastFrame'{
|
||||||
task_id = TaskId,
|
body = {event_stream, #'TaskEventStream'{task_id = TaskId, type = Type, stream = Stream}}
|
||||||
type = Type,
|
|
||||||
stream = Stream
|
|
||||||
}),
|
}),
|
||||||
efka_transport:send(TransportPid, EventPacket),
|
efka_transport:send(TransportPid, EventPacket),
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
handle_event(cast, {close_task_event_stream, TaskId, Reason}, ?STATE_ACTIVATED, State = #state{transport_pid = TransportPid}) ->
|
handle_event(cast, {close_task_event_stream, TaskId, Reason}, ?STATE_ACTIVATED, State = #state{transport_pid = TransportPid}) ->
|
||||||
EventPacket = message_codec:encode(?MESSAGE_EVENT_STREAM, #'TaskEventStream'{
|
EventPacket = message_pb:encode_msg(#'CastFrame'{
|
||||||
task_id = TaskId,
|
body = {event_stream, #'TaskEventStream'{task_id = TaskId, type = <<"close">>, stream = Reason}}
|
||||||
type = <<"close">>,
|
|
||||||
stream = Reason
|
|
||||||
}),
|
}),
|
||||||
efka_transport:send(TransportPid, EventPacket),
|
efka_transport:send(TransportPid, EventPacket),
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
@ -144,7 +138,7 @@ handle_event(cast, {task_event_stream, _TaskId, _Stream}, _, State = #state{}) -
|
|||||||
% memory = Memory,
|
% memory = Memory,
|
||||||
% interfaces = Interfaces
|
% interfaces = Interfaces
|
||||||
% }),
|
% }),
|
||||||
% efka_transport:send(TransportPid, ?METHOD_PING, Ping),
|
% efka_transport:send(TransportPid, Ping),
|
||||||
% {keep_state, State};
|
% {keep_state, State};
|
||||||
|
|
||||||
%% 异步建立到服务器的连接
|
%% 异步建立到服务器的连接
|
||||||
@ -160,43 +154,39 @@ handle_event(info, {timeout, _, create_transport}, ?STATE_DENIED, State) ->
|
|||||||
handle_event(info, {connect_reply, Reply}, ?STATE_CONNECTING, State = #state{transport_pid = TransportPid}) ->
|
handle_event(info, {connect_reply, Reply}, ?STATE_CONNECTING, State = #state{transport_pid = TransportPid}) ->
|
||||||
case Reply of
|
case Reply of
|
||||||
ok ->
|
ok ->
|
||||||
AuthRequest = auth_request(),
|
AuthPacket = auth_packet(),
|
||||||
efka_transport:auth_request(TransportPid, AuthRequest),
|
efka_transport:send(TransportPid, AuthPacket),
|
||||||
{next_state, ?STATE_AUTH, State};
|
{next_state, ?STATE_AUTH, State, [{state_timeout, 5000, auth_timeout}]};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
logger:debug("[efka_remote_agent] connect failed, error: ~p, pid: ~p", [Reason, TransportPid]),
|
logger:debug("[efka_remote_agent] connect failed, error: ~p, pid: ~p", [Reason, TransportPid]),
|
||||||
efka_transport:stop(TransportPid),
|
efka_transport:stop(TransportPid),
|
||||||
{next_state, ?STATE_DENIED, State#state{transport_pid = undefined}}
|
{next_state, ?STATE_DENIED, State#state{transport_pid = undefined}}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_event(info, {auth_reply, Reply}, ?STATE_AUTH, State = #state{transport_pid = TransportPid}) ->
|
handle_event(info, {server_packet, PacketBin}, ?STATE_AUTH, State = #state{transport_pid = TransportPid}) ->
|
||||||
case Reply of
|
#'ResponseFrame'{packet_id = 1, body = {auth_reply, #'AuthReply'{code = Code, payload = Message}}} =
|
||||||
{ok, #'AuthReply'{code = Code, payload = Message}} ->
|
message_pb:decode_msg(PacketBin, 'ResponseFrame'),
|
||||||
case Code of
|
case Code of
|
||||||
0 ->
|
0 ->
|
||||||
logger:debug("[efka_remote_agent] auth success, message: ~p", [Message]),
|
logger:debug("[efka_remote_agent] auth success, message: ~p", [Message]),
|
||||||
{next_state, ?STATE_ACTIVATED, State, [{next_event, info, flush_cache}]};
|
{next_state, ?STATE_ACTIVATED, State, [{next_event, info, flush_cache}]};
|
||||||
1 ->
|
1 ->
|
||||||
%% 主机在后台的授权未通过;此时agent不能推送数据给云端服务器,但是云端服务器可以推送命令给agent
|
|
||||||
%% socket的连接状态需要维持
|
|
||||||
logger:debug("[efka_remote_agent] auth denied, message: ~p", [Message]),
|
logger:debug("[efka_remote_agent] auth denied, message: ~p", [Message]),
|
||||||
{next_state, ?STATE_RESTRICTED, State};
|
{next_state, ?STATE_RESTRICTED, State};
|
||||||
2 ->
|
2 ->
|
||||||
% 其他类型的错误,需要间隔时间重试
|
|
||||||
logger:debug("[efka_remote_agent] auth failed, message: ~p", [Message]),
|
logger:debug("[efka_remote_agent] auth failed, message: ~p", [Message]),
|
||||||
efka_transport:stop(TransportPid),
|
efka_transport:stop(TransportPid),
|
||||||
{next_state, ?STATE_DENIED, State#state{transport_pid = undefined}};
|
{next_state, ?STATE_DENIED, State#state{transport_pid = undefined}};
|
||||||
_ ->
|
_ ->
|
||||||
% 其他类型的错误,需要间隔时间重试
|
|
||||||
logger:debug("[efka_remote_agent] auth failed, invalid message"),
|
logger:debug("[efka_remote_agent] auth failed, invalid message"),
|
||||||
efka_transport:stop(TransportPid),
|
efka_transport:stop(TransportPid),
|
||||||
{next_state, ?STATE_DENIED, State#state{transport_pid = undefined}}
|
{next_state, ?STATE_DENIED, State#state{transport_pid = undefined}}
|
||||||
end;
|
end;
|
||||||
{error, Reason} ->
|
|
||||||
logger:debug("[efka_remote_agent] auth_request failed, error: ~p", [Reason]),
|
handle_event(state_timeout, auth_timeout, ?STATE_AUTH, State = #state{transport_pid = TransportPid}) ->
|
||||||
|
logger:debug("[efka_remote_agent] auth request timeout"),
|
||||||
efka_transport:stop(TransportPid),
|
efka_transport:stop(TransportPid),
|
||||||
{next_state, ?STATE_DENIED, State#state{transport_pid = undefined}}
|
{next_state, ?STATE_DENIED, State#state{transport_pid = undefined}};
|
||||||
end;
|
|
||||||
|
|
||||||
%% 将缓存中的数据推送到服务器端
|
%% 将缓存中的数据推送到服务器端
|
||||||
handle_event(info, flush_cache, ?STATE_ACTIVATED, State = #state{transport_pid = TransportPid}) ->
|
handle_event(info, flush_cache, ?STATE_ACTIVATED, State = #state{transport_pid = TransportPid}) ->
|
||||||
@ -211,6 +201,30 @@ handle_event(info, flush_cache, ?STATE_ACTIVATED, State = #state{transport_pid =
|
|||||||
handle_event(info, flush_cache, _, State) ->
|
handle_event(info, flush_cache, _, State) ->
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
|
handle_event(info, {server_packet, <<8, _/binary>> = PacketBin}, ?STATE_ACTIVATED, State) ->
|
||||||
|
#'RequestFrame'{packet_id = PacketId, body = {rpc_request, Request}} =
|
||||||
|
message_pb:decode_msg(PacketBin, 'RequestFrame'),
|
||||||
|
true = is_integer(PacketId) andalso PacketId > 0,
|
||||||
|
{keep_state, State, [{next_event, info, {server_rpc, PacketId, Request}}]};
|
||||||
|
handle_event(info, {server_packet, <<10, _/binary>> = PacketBin}, ?STATE_ACTIVATED, State) ->
|
||||||
|
#'CastFrame'{body = {pub, Pub}} = message_pb:decode_msg(PacketBin, 'CastFrame'),
|
||||||
|
{keep_state, State, [{next_event, info, {server_cast, Pub}}]};
|
||||||
|
handle_event(info, {server_packet, <<18, _/binary>> = PacketBin}, ?STATE_ACTIVATED, State) ->
|
||||||
|
#'CastFrame'{body = {command, Command}} = message_pb:decode_msg(PacketBin, 'CastFrame'),
|
||||||
|
{keep_state, State, [{next_event, info, {server_cast, Command}}]};
|
||||||
|
|
||||||
|
handle_event(info, {server_packet, <<8, _/binary>> = PacketBin}, ?STATE_RESTRICTED, State) ->
|
||||||
|
#'RequestFrame'{packet_id = PacketId, body = {rpc_request, Request}} =
|
||||||
|
message_pb:decode_msg(PacketBin, 'RequestFrame'),
|
||||||
|
true = is_integer(PacketId) andalso PacketId > 0,
|
||||||
|
{keep_state, State, [{next_event, info, {server_rpc, PacketId, Request}}]};
|
||||||
|
handle_event(info, {server_packet, <<10, _/binary>> = PacketBin}, ?STATE_RESTRICTED, State) ->
|
||||||
|
#'CastFrame'{body = {pub, Pub}} = message_pb:decode_msg(PacketBin, 'CastFrame'),
|
||||||
|
{keep_state, State, [{next_event, info, {server_cast, Pub}}]};
|
||||||
|
handle_event(info, {server_packet, <<18, _/binary>> = PacketBin}, ?STATE_RESTRICTED, State) ->
|
||||||
|
#'CastFrame'{body = {command, Command}} = message_pb:decode_msg(PacketBin, 'CastFrame'),
|
||||||
|
{keep_state, State, [{next_event, info, {server_cast, Command}}]};
|
||||||
|
|
||||||
%% 云端服务器推送了消息
|
%% 云端服务器推送了消息
|
||||||
%% 激活消息
|
%% 激活消息
|
||||||
|
|
||||||
@ -219,9 +233,21 @@ handle_event(info, {server_rpc, PacketId, #'RpcRequest'{method = <<"get_containe
|
|||||||
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
||||||
case docker_manager:get_containers() of
|
case docker_manager:get_containers() of
|
||||||
{ok, Containers} ->
|
{ok, Containers} ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_success(Containers));
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {result, #'RpcReply.RpcResult'{data = encode_rpc_payload(Containers)}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet);
|
||||||
{error, Reason} when is_binary(Reason) ->
|
{error, Reason} when is_binary(Reason) ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_error(-1, Reason))
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {error, #'RpcReply.RpcError'{code = -1, message = Reason}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet)
|
||||||
end,
|
end,
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
@ -231,9 +257,21 @@ handle_event(info, {server_rpc, PacketId, #'RpcRequest'{method = <<"deploy">>, p
|
|||||||
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
||||||
case docker_manager:deploy(TaskId, Config) of
|
case docker_manager:deploy(TaskId, Config) of
|
||||||
ok ->
|
ok ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_success(<<"ok">>));
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {result, #'RpcReply.RpcResult'{data = encode_rpc_payload(<<"ok">>)}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet);
|
||||||
{error, Reason} when is_binary(Reason) ->
|
{error, Reason} when is_binary(Reason) ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_error(-1, Reason))
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {error, #'RpcReply.RpcError'{code = -1, message = Reason}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet)
|
||||||
end,
|
end,
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
@ -243,9 +281,21 @@ handle_event(info, {server_rpc, PacketId, #'RpcRequest'{method = <<"start_contai
|
|||||||
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
||||||
case docker_manager:start_container(ContainerName) of
|
case docker_manager:start_container(ContainerName) of
|
||||||
ok ->
|
ok ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_success(<<"ok">>));
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {result, #'RpcReply.RpcResult'{data = encode_rpc_payload(<<"ok">>)}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet);
|
||||||
{error, Reason} when is_binary(Reason) ->
|
{error, Reason} when is_binary(Reason) ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_error(-1, Reason))
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {error, #'RpcReply.RpcError'{code = -1, message = Reason}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet)
|
||||||
end,
|
end,
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
@ -255,9 +305,21 @@ handle_event(info, {server_rpc, PacketId, #'RpcRequest'{method = <<"stop_contain
|
|||||||
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
||||||
case docker_manager:stop_container(ContainerName) of
|
case docker_manager:stop_container(ContainerName) of
|
||||||
ok ->
|
ok ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_success(<<"ok">>));
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {result, #'RpcReply.RpcResult'{data = encode_rpc_payload(<<"ok">>)}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet);
|
||||||
{error, Reason} when is_binary(Reason) ->
|
{error, Reason} when is_binary(Reason) ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_error(-1, Reason))
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {error, #'RpcReply.RpcError'{code = -1, message = Reason}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet)
|
||||||
end,
|
end,
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
@ -266,9 +328,21 @@ handle_event(info, {server_rpc, PacketId, #'RpcRequest'{method = <<"kill_contain
|
|||||||
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
||||||
case docker_manager:kill_container(ContainerName) of
|
case docker_manager:kill_container(ContainerName) of
|
||||||
ok ->
|
ok ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_success(<<"ok">>));
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {result, #'RpcReply.RpcResult'{data = encode_rpc_payload(<<"ok">>)}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet);
|
||||||
{error, Reason} when is_binary(Reason) ->
|
{error, Reason} when is_binary(Reason) ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_error(-1, Reason))
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {error, #'RpcReply.RpcError'{code = -1, message = Reason}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet)
|
||||||
end,
|
end,
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
@ -277,9 +351,21 @@ handle_event(info, {server_rpc, PacketId, #'RpcRequest'{method = <<"remove_conta
|
|||||||
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
%% 短暂的等待,efka_inetd收到消息后就立即返回了
|
||||||
case docker_manager:remove_container(ContainerName) of
|
case docker_manager:remove_container(ContainerName) of
|
||||||
ok ->
|
ok ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_success(<<"ok">>));
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {result, #'RpcReply.RpcResult'{data = encode_rpc_payload(<<"ok">>)}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet);
|
||||||
{error, Reason} when is_binary(Reason) ->
|
{error, Reason} when is_binary(Reason) ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_error(-1, Reason))
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {error, #'RpcReply.RpcError'{code = -1, message = Reason}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet)
|
||||||
end,
|
end,
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
@ -288,9 +374,21 @@ handle_event(info, {server_rpc, PacketId, #'RpcRequest'{method = <<"config_conta
|
|||||||
#{<<"container_name">> := ContainerName, <<"config">> := Config} = decode_rpc_payload(ParamsBin),
|
#{<<"container_name">> := ContainerName, <<"config">> := Config} = decode_rpc_payload(ParamsBin),
|
||||||
case docker_manager:config_container(ContainerName, Config) of
|
case docker_manager:config_container(ContainerName, Config) of
|
||||||
ok ->
|
ok ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_success(<<"ok">>));
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {result, #'RpcReply.RpcResult'{data = encode_rpc_payload(<<"ok">>)}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet);
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
efka_transport:rpc_reply(TransportPid, PacketId, reply_error(-1, Reason))
|
Packet = message_pb:encode_msg(#'ResponseFrame'{
|
||||||
|
packet_id = PacketId,
|
||||||
|
body = {rpc_reply, #'RpcReply'{
|
||||||
|
reply = {error, #'RpcReply.RpcError'{code = -1, message = Reason}}
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
efka_transport:send(TransportPid, Packet)
|
||||||
end,
|
end,
|
||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
|
|
||||||
@ -306,7 +404,7 @@ handle_event(info, {server_rpc, PacketId, #'RpcRequest'{method = <<"config_conta
|
|||||||
% false ->
|
% false ->
|
||||||
% #async_call_reply{code = 1, result = <<"[]">>}
|
% #async_call_reply{code = 1, result = <<"[]">>}
|
||||||
% end,
|
% end,
|
||||||
% efka_transport:async_call_reply(TransportPid, PacketId, message_pb:encode_msg(Reply)),
|
% efka_transport:send(TransportPid, message_pb:encode_msg(Reply)),
|
||||||
%
|
%
|
||||||
% {keep_state, State};
|
% {keep_state, State};
|
||||||
|
|
||||||
@ -318,9 +416,9 @@ handle_event(info, {server_cast, #'Command'{command_type = ?COMMAND_AUTH, comman
|
|||||||
{keep_state, State};
|
{keep_state, State};
|
||||||
{1, ?STATE_DENIED} ->
|
{1, ?STATE_DENIED} ->
|
||||||
%% 重新激活, 需要重新校验
|
%% 重新激活, 需要重新校验
|
||||||
AuthRequest = auth_request(),
|
AuthPacket = auth_packet(),
|
||||||
efka_transport:auth_request(TransportPid, AuthRequest),
|
efka_transport:send(TransportPid, AuthPacket),
|
||||||
{next_state, ?STATE_AUTH, State};
|
{next_state, ?STATE_AUTH, State, [{state_timeout, 5000, auth_timeout}]};
|
||||||
{0, _} ->
|
{0, _} ->
|
||||||
%% 这个时候的主机应该是受限制的状态,不允许发送消息;但是能够接受服务器推送的消息
|
%% 这个时候的主机应该是受限制的状态,不允许发送消息;但是能够接受服务器推送的消息
|
||||||
{next_state, ?STATE_RESTRICTED, State}
|
{next_state, ?STATE_RESTRICTED, State}
|
||||||
@ -362,33 +460,24 @@ code_change(_OldVsn, StateName, State = #state{}, _Extra) ->
|
|||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
|
||||||
-spec auth_request() -> message_pb:'AuthRequest'().
|
-spec auth_packet() -> binary().
|
||||||
auth_request() ->
|
auth_packet() ->
|
||||||
|
%% 重新激活, 需要重新校验
|
||||||
{ok, AuthInfo} = application:get_env(efka, auth),
|
{ok, AuthInfo} = application:get_env(efka, auth),
|
||||||
UUID = proplists:get_value(uuid, AuthInfo),
|
UUID = proplists:get_value(uuid, AuthInfo),
|
||||||
Username = proplists:get_value(username, AuthInfo),
|
Username = proplists:get_value(username, AuthInfo),
|
||||||
Salt = proplists:get_value(salt, AuthInfo),
|
Salt = proplists:get_value(salt, AuthInfo),
|
||||||
Token = proplists:get_value(token, AuthInfo),
|
Token = proplists:get_value(token, AuthInfo),
|
||||||
|
message_pb:encode_msg(#'RequestFrame'{
|
||||||
#'AuthRequest'{
|
packet_id = 1,
|
||||||
|
body = {auth_request, #'AuthRequest'{
|
||||||
uuid = unicode:characters_to_binary(UUID),
|
uuid = unicode:characters_to_binary(UUID),
|
||||||
username = unicode:characters_to_binary(Username),
|
username = unicode:characters_to_binary(Username),
|
||||||
salt = unicode:characters_to_binary(Salt),
|
salt = unicode:characters_to_binary(Salt),
|
||||||
token = unicode:characters_to_binary(Token),
|
token = unicode:characters_to_binary(Token),
|
||||||
timestamp = efka_util:timestamp()
|
timestamp = efka_util:timestamp()
|
||||||
}.
|
}}
|
||||||
|
}).
|
||||||
-spec reply_success(Result :: any()) -> message_pb:'RpcReply'().
|
|
||||||
reply_success(Result) ->
|
|
||||||
#'RpcReply'{
|
|
||||||
reply = {result, #'RpcReply.RpcResult'{data = encode_rpc_payload(Result)}}
|
|
||||||
}.
|
|
||||||
|
|
||||||
-spec reply_error(Code :: integer(), Message :: binary()) -> message_pb:'RpcReply'().
|
|
||||||
reply_error(Code, Message) when is_integer(Code), is_binary(Message) ->
|
|
||||||
#'RpcReply'{
|
|
||||||
reply = {error, #'RpcReply.RpcError'{code = Code, message = Message}}
|
|
||||||
}.
|
|
||||||
|
|
||||||
-spec decode_rpc_payload(binary()) -> any().
|
-spec decode_rpc_payload(binary()) -> any().
|
||||||
decode_rpc_payload(<<>>) ->
|
decode_rpc_payload(<<>>) ->
|
||||||
|
|||||||
@ -8,13 +8,12 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(efka_transport).
|
-module(efka_transport).
|
||||||
-author("anlicheng").
|
-author("anlicheng").
|
||||||
-include("message.hrl").
|
|
||||||
|
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start_monitor/3]).
|
-export([start_monitor/3]).
|
||||||
-export([connect/1, auth_request/2, send/2, rpc_reply/3, stop/1]).
|
-export([connect/1, send/2, stop/1]).
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
|
||||||
@ -28,14 +27,6 @@
|
|||||||
socket :: undefined | ssl:sslsocket()
|
socket :: undefined | ssl:sslsocket()
|
||||||
}).
|
}).
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% API
|
|
||||||
%%%===================================================================
|
|
||||||
|
|
||||||
-spec auth_request(Pid :: pid(), AuthRequest :: any()) -> no_return().
|
|
||||||
auth_request(Pid, AuthRequest) when is_pid(Pid) ->
|
|
||||||
gen_server:cast(Pid, {auth_request, AuthRequest}).
|
|
||||||
|
|
||||||
-spec connect(Pid :: pid()) -> no_return().
|
-spec connect(Pid :: pid()) -> no_return().
|
||||||
connect(Pid) when is_pid(Pid) ->
|
connect(Pid) when is_pid(Pid) ->
|
||||||
gen_server:cast(Pid, connect).
|
gen_server:cast(Pid, connect).
|
||||||
@ -44,12 +35,6 @@ connect(Pid) when is_pid(Pid) ->
|
|||||||
send(Pid, Packet) when is_pid(Pid), is_binary(Packet) ->
|
send(Pid, Packet) when is_pid(Pid), is_binary(Packet) ->
|
||||||
gen_server:cast(Pid, {send, Packet}).
|
gen_server:cast(Pid, {send, Packet}).
|
||||||
|
|
||||||
-spec rpc_reply(Pid :: pid() | undefined, PacketId :: integer(), Response :: any()) -> no_return().
|
|
||||||
rpc_reply(undefined, PacketId, _Response) when is_integer(PacketId) ->
|
|
||||||
ok;
|
|
||||||
rpc_reply(Pid, PacketId, Reply) when is_pid(Pid), is_integer(PacketId) ->
|
|
||||||
gen_server:cast(Pid, {rpc_reply, PacketId, Reply}).
|
|
||||||
|
|
||||||
%% 关闭的时候不一定能成功,可能关闭的时候;transport进程已经退出了
|
%% 关闭的时候不一定能成功,可能关闭的时候;transport进程已经退出了
|
||||||
-spec stop(Pid :: pid() | undefined) -> ok.
|
-spec stop(Pid :: pid() | undefined) -> ok.
|
||||||
stop(undefined) ->
|
stop(undefined) ->
|
||||||
@ -111,37 +96,7 @@ handle_cast(connect, State = #state{host = Host, port = Port, parent_pid = Paren
|
|||||||
{noreply, State#state{socket = undefined}}
|
{noreply, State#state{socket = undefined}}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
%% auth校验
|
|
||||||
handle_cast({auth_request, AuthRequest}, State = #state{parent_pid = ParentPid, socket = Socket}) ->
|
|
||||||
PacketId = 1,
|
|
||||||
Packet = message_codec:encode_request(PacketId, ?MESSAGE_AUTH_REQUEST, AuthRequest),
|
|
||||||
ok = ssl:send(Socket, Packet),
|
|
||||||
%% 需要等待auth返回的结果
|
|
||||||
receive
|
|
||||||
{ssl, Socket, ReplyBin} ->
|
|
||||||
case message_codec:decode_response(ReplyBin) of
|
|
||||||
{ok, PacketId, Reply} ->
|
|
||||||
ParentPid ! {auth_reply, {ok, Reply}};
|
|
||||||
{ok, ReplyPacketId, _Reply} ->
|
|
||||||
logger:warning("[efka_transport] get unexpected auth_reply packet_id: ~p", [ReplyPacketId]),
|
|
||||||
ParentPid ! {auth_reply, {error, invalid_auth_reply}};
|
|
||||||
error ->
|
|
||||||
logger:warning("[efka_transport] get invalid auth_reply: ~p", [ReplyBin]),
|
|
||||||
ParentPid ! {auth_reply, {error, invalid_auth_reply}}
|
|
||||||
end,
|
|
||||||
{noreply, State}
|
|
||||||
after 5000 ->
|
|
||||||
ParentPid ! {auth_reply, {error, timeout}},
|
|
||||||
{noreply, State}
|
|
||||||
end;
|
|
||||||
|
|
||||||
handle_cast({send, Packet}, State = #state{socket = Socket}) ->
|
handle_cast({send, Packet}, State = #state{socket = Socket}) ->
|
||||||
ok = ssl:send(Socket, Packet),
|
|
||||||
{noreply, State};
|
|
||||||
|
|
||||||
%% 服务push的消息的回复
|
|
||||||
handle_cast({rpc_reply, PacketId, Reply}, State = #state{socket = Socket}) ->
|
|
||||||
Packet = message_codec:encode_response(PacketId, ?MESSAGE_JSONRPC_REPLY, Reply),
|
|
||||||
ok = ssl:send(Socket, Packet),
|
ok = ssl:send(Socket, Packet),
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
@ -153,17 +108,7 @@ handle_cast({rpc_reply, PacketId, Reply}, State = #state{socket = Socket}) ->
|
|||||||
{stop, Reason :: term(), NewState :: #state{}}).
|
{stop, Reason :: term(), NewState :: #state{}}).
|
||||||
%% 服务器主动推送的数据
|
%% 服务器主动推送的数据
|
||||||
handle_info({ssl, Socket, PacketBin}, State = #state{socket = Socket, parent_pid = ParentPid}) ->
|
handle_info({ssl, Socket, PacketBin}, State = #state{socket = Socket, parent_pid = ParentPid}) ->
|
||||||
case message_codec:decode_request(PacketBin) of
|
ParentPid ! {server_packet, PacketBin},
|
||||||
{ok, PacketId, Request} ->
|
|
||||||
ParentPid ! {server_rpc, PacketId, Request};
|
|
||||||
error ->
|
|
||||||
case message_codec:decode_cast(PacketBin) of
|
|
||||||
{ok, CastRequest} ->
|
|
||||||
ParentPid ! {server_cast, CastRequest};
|
|
||||||
error ->
|
|
||||||
logger:warning("[efka_transport] get invalid packet: ~p", [PacketBin])
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
|
||||||
handle_info({ssl_error, Socket, Reason}, State = #state{socket = Socket}) ->
|
handle_info({ssl_error, Socket, Reason}, State = #state{socket = Socket}) ->
|
||||||
|
|||||||
@ -1,130 +0,0 @@
|
|||||||
%%%-------------------------------------------------------------------
|
|
||||||
%%% @author anlicheng
|
|
||||||
%%% @copyright (C) 2025, <COMPANY>
|
|
||||||
%%% @doc
|
|
||||||
%%%
|
|
||||||
%%% @end
|
|
||||||
%%% Created : 17. 9月 2025 16:05
|
|
||||||
%%%-------------------------------------------------------------------
|
|
||||||
-module(message_codec).
|
|
||||||
-author("anlicheng").
|
|
||||||
-include("message.hrl").
|
|
||||||
-include("message_pb.hrl").
|
|
||||||
|
|
||||||
%% API
|
|
||||||
-export([encode/2, encode_request/3, encode_response/3]).
|
|
||||||
-export([decode_request/1, decode_response/1, decode_cast/1]).
|
|
||||||
|
|
||||||
-spec encode(MessageType :: integer(), Message :: any()) -> binary().
|
|
||||||
encode(MessageType, Message) when is_integer(MessageType) ->
|
|
||||||
case frame_for_type(MessageType, Message, 0) of
|
|
||||||
{request, Frame} ->
|
|
||||||
message_pb:encode_msg(Frame);
|
|
||||||
{response, Frame} ->
|
|
||||||
message_pb:encode_msg(Frame);
|
|
||||||
{cast, Frame} ->
|
|
||||||
message_pb:encode_msg(Frame)
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec encode_request(PacketId :: integer(), MessageType :: integer(), Message :: any()) -> binary().
|
|
||||||
encode_request(PacketId, MessageType, Message) when is_integer(PacketId), is_integer(MessageType) ->
|
|
||||||
case frame_for_type(MessageType, Message, PacketId) of
|
|
||||||
{request, Frame} ->
|
|
||||||
message_pb:encode_msg(Frame);
|
|
||||||
_ ->
|
|
||||||
erlang:error({unsupported_request_type, MessageType})
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec encode_response(PacketId :: integer(), MessageType :: integer(), Message :: any()) -> binary().
|
|
||||||
encode_response(PacketId, MessageType, Message) when is_integer(PacketId), is_integer(MessageType) ->
|
|
||||||
case frame_for_type(MessageType, Message, PacketId) of
|
|
||||||
{response, Frame} ->
|
|
||||||
message_pb:encode_msg(Frame);
|
|
||||||
_ ->
|
|
||||||
erlang:error({unsupported_response_type, MessageType})
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec decode_request(Bin :: binary()) -> {ok, PacketId :: integer(), Message :: any()} | error.
|
|
||||||
decode_request(Bin) when is_binary(Bin) ->
|
|
||||||
try
|
|
||||||
Frame = message_pb:decode_msg(Bin, 'RequestFrame'),
|
|
||||||
decode_request_frame(Frame)
|
|
||||||
catch
|
|
||||||
_:_ ->
|
|
||||||
error
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec decode_response(Bin :: binary()) -> {ok, PacketId :: integer(), Message :: any()} | error.
|
|
||||||
decode_response(Bin) when is_binary(Bin) ->
|
|
||||||
try
|
|
||||||
Frame = message_pb:decode_msg(Bin, 'ResponseFrame'),
|
|
||||||
decode_response_frame(Frame)
|
|
||||||
catch
|
|
||||||
_:_ ->
|
|
||||||
error
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec decode_cast(Bin :: binary()) -> {ok, Message :: any()} | error.
|
|
||||||
decode_cast(Bin) when is_binary(Bin) ->
|
|
||||||
try
|
|
||||||
Frame = message_pb:decode_msg(Bin, 'CastFrame'),
|
|
||||||
decode_cast_frame(Frame)
|
|
||||||
catch
|
|
||||||
_:_ ->
|
|
||||||
error
|
|
||||||
end.
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
%%% helper methods
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
frame_for_type(?MESSAGE_AUTH_REQUEST, Message = #'AuthRequest'{}, PacketId) ->
|
|
||||||
{request, #'RequestFrame'{packet_id = PacketId, body = {auth_request, Message}}};
|
|
||||||
frame_for_type(?MESSAGE_JSONRPC_REQUEST, Message = #'RpcRequest'{}, PacketId) ->
|
|
||||||
{request, #'RequestFrame'{packet_id = PacketId, body = {rpc_request, Message}}};
|
|
||||||
frame_for_type(?MESSAGE_AUTH_REPLY, Message = #'AuthReply'{}, PacketId) ->
|
|
||||||
{response, #'ResponseFrame'{packet_id = PacketId, body = {auth_reply, Message}}};
|
|
||||||
frame_for_type(?MESSAGE_JSONRPC_REPLY, Message = #'RpcReply'{}, PacketId) ->
|
|
||||||
{response, #'ResponseFrame'{packet_id = PacketId, body = {rpc_reply, Message}}};
|
|
||||||
frame_for_type(?MESSAGE_PUB, Message = #'Pub'{}, _PacketId) ->
|
|
||||||
{cast, #'CastFrame'{body = {pub, Message}}};
|
|
||||||
frame_for_type(?MESSAGE_COMMAND, Message = #'Command'{}, _PacketId) ->
|
|
||||||
{cast, #'CastFrame'{body = {command, Message}}};
|
|
||||||
frame_for_type(?MESSAGE_DATA, Message = #'Data'{}, _PacketId) ->
|
|
||||||
{cast, #'CastFrame'{body = {data, Message}}};
|
|
||||||
frame_for_type(?MESSAGE_EVENT_STREAM, Message = #'TaskEventStream'{}, _PacketId) ->
|
|
||||||
{cast, #'CastFrame'{body = {event_stream, Message}}};
|
|
||||||
frame_for_type(MessageType, Message, _PacketId) ->
|
|
||||||
erlang:error({unsupported_message_type, MessageType, Message}).
|
|
||||||
|
|
||||||
decode_request_frame(#'RequestFrame'{packet_id = PacketId, body = {auth_request, Message}})
|
|
||||||
when is_integer(PacketId), PacketId > 0 ->
|
|
||||||
{ok, PacketId, Message};
|
|
||||||
decode_request_frame(#'RequestFrame'{packet_id = PacketId, body = {rpc_request, Message}})
|
|
||||||
when is_integer(PacketId), PacketId > 0 ->
|
|
||||||
{ok, PacketId, Message};
|
|
||||||
decode_request_frame(#'RequestFrame'{packet_id = PacketId, body = {container_request, Message}})
|
|
||||||
when is_integer(PacketId), PacketId > 0 ->
|
|
||||||
{ok, PacketId, Message};
|
|
||||||
decode_request_frame(_) ->
|
|
||||||
error.
|
|
||||||
|
|
||||||
decode_response_frame(#'ResponseFrame'{packet_id = PacketId, body = {auth_reply, Message}})
|
|
||||||
when is_integer(PacketId), PacketId > 0 ->
|
|
||||||
{ok, PacketId, Message};
|
|
||||||
decode_response_frame(#'ResponseFrame'{packet_id = PacketId, body = {rpc_reply, Message}})
|
|
||||||
when is_integer(PacketId), PacketId > 0 ->
|
|
||||||
{ok, PacketId, Message};
|
|
||||||
decode_response_frame(_) ->
|
|
||||||
error.
|
|
||||||
|
|
||||||
decode_cast_frame(#'CastFrame'{body = {pub, Message}}) ->
|
|
||||||
{ok, Message};
|
|
||||||
decode_cast_frame(#'CastFrame'{body = {command, Message}}) ->
|
|
||||||
{ok, Message};
|
|
||||||
decode_cast_frame(#'CastFrame'{body = {data, Message}}) ->
|
|
||||||
{ok, Message};
|
|
||||||
decode_cast_frame(#'CastFrame'{body = {event_stream, Message}}) ->
|
|
||||||
{ok, Message};
|
|
||||||
decode_cast_frame(_) ->
|
|
||||||
error.
|
|
||||||
6101
src/protobuf/message_pb.erl
Normal file
6101
src/protobuf/message_pb.erl
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user