%% 获取进程状态
info(PState) ->
maps:from_list(info([conninfo,conn_state,clientinfo,session,will_msg],PState)).
info(Keys, PState) when is_list(Keys) ->[{Key, info(Key, PState)} || Key <- Keys];
%% 连接状态
info(conninfo, PState) -> conninfo(PState);
%% 客户信息
info(clientinfo, PState) -> clientinfo(PState);
%% session信息
info(session, _) -> undefined;
%% 连接状态
info(conn_state, #pstate{connected = Connected}) ->Connected;
%% 意愿消息
info(will_msg, _) -> undefined.
%% 客户端id
client_id(#pstate{client_id = ClientId}) -> ClientId.
%% 统计数据
stats(#pstate{recv_stats = #{pkt := RecvPkt, msg := RecvMsg},send_stats = #{pkt := SendPkt, msg := SendMsg}}) ->
[{recv_pkt, RecvPkt},{recv_msg, RecvMsg},{send_pkt, SendPkt},{send_msg, SendMsg}].
start_keepalive(0, _PState) -> ignore;
start_keepalive(Secs, _PState) when Secs > 0 ->
self() ! {keepalive, start, round(Secs)}.
clientinfo(#pstate{client_id = ClientId,
username = Username, peername = {Peerhost, _},peercert = Peercert}) ->
with_cert(#{zone => undefined, protocol => tcp,
peerhost => Peerhost, clientid => ClientId,
username => Username, peercert => Peercert,
is_bridge => false, is_supuser => false,
mountpoint => undefined, ws_cookie => undefined,
sockport => 8090},
Peercert).
with_cert(ClientInfo, undefined) -> ClientInfo;
with_cert(ClientInfo, Peercert) ->
ClientInfo#{dn => esockd_peercert:subject(Peercert),
cn => esockd_peercert:common_name(Peercert)}.
conninfo(#pstate{sockname = Sockname,
peername = Peername, peercert = Peercert,
client_id = ClientId, username = Username,
keepalive = Keepalive, connected = Connected,
connected_at = ConnectedAt, conn_mod = ConnMod,
proto_ver = ProtoVer}) ->
#{socktype => tcp, sockname => Sockname,
peername => Peername, peercert => Peercert,
conn_mod => ConnMod, proto_name => <<"tcp">>,
proto_ver => ProtoVer, clean_start => true,
clientid => ClientId, username => Username,
conn_props => [], connected => Connected,
connected_at => ConnectedAt, keepalive => Keepalive,
receive_maximum => 0, expiry_interval => 0}.
prepare_adapter_topic(PState = #pstate{up_topic = UpTopic,dn_topic = DnTopic}) ->
PState#pstate{up_topic = replvar(UpTopic, PState),dn_topic = replvar(DnTopic, PState)}.
replvar(undefined, _PState) -> undefined;
replvar(Topic,#pstate{client_id = ClientId, username = Username}) ->
iolist_to_binary(re:replace(re:replace(Topic,"%c",ClientId),"%u", to_binary(Username))).
autosubcribe(#pstate{dn_topic = Topic})when Topic == undefined; Topic == "" ->ok;
autosubcribe(PState = #pstate{dn_topic = Topic,client_id = ClientId}) ->
SubOpts = #{rap => 0, nl => 0, qos => 0, rh => 0},
emqx:subscribe(Topic, ClientId, SubOpts),
ok = emqx_hooks:run('session.subscribed',[clientinfo(PState), Topic, SubOpts#{is_new => true}]).
connack({0, PState}) ->
_ = run_hooks('client.connack',[conninfo(PState), success],undefined),
run_hooks('client.connected',[clientinfo(PState), conninfo(PState)]),
deliver({connack, 0, <<"Connect Successfully">>},PState);
connack({Code, Msg, PState}) ->
_ = run_hooks('client.connack',[conninfo(PState), not_authorized],undefined),
deliver({connack, Code, Msg}, PState).
do_publish(#tcp_packet_datatrans{data = Data},PState = #pstate{up_topic = Topic}) ->
Msg = emqx_message:make(emqx_tcp_connector,Topic,Data),
emqx:publish(Msg),
{ok, PState}.