subscription
This commit is contained in:
parent
e37b00a9e4
commit
fe82fde717
|
@ -19,11 +19,11 @@
|
||||||
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
%%% SOFTWARE.
|
%%% SOFTWARE.
|
||||||
%%%-----------------------------------------------------------------------------
|
%%%-----------------------------------------------------------------------------
|
||||||
%%% @doc emqttd auto subscribe module.
|
%%% @doc Subscription from Broker Side
|
||||||
%%%
|
%%%
|
||||||
%%% @author Feng Lee <feng@emqtt.io>
|
%%% @author Feng Lee <feng@emqtt.io>
|
||||||
%%%-----------------------------------------------------------------------------
|
%%%-----------------------------------------------------------------------------
|
||||||
-module(emqttd_mod_autosub).
|
-module(emqttd_mod_subscription).
|
||||||
|
|
||||||
-behaviour(emqttd_gen_mod).
|
-behaviour(emqttd_gen_mod).
|
||||||
|
|
||||||
|
@ -33,29 +33,45 @@
|
||||||
|
|
||||||
-export([load/1, client_connected/3, unload/1]).
|
-export([load/1, client_connected/3, unload/1]).
|
||||||
|
|
||||||
-record(state, {topics}).
|
-record(state, {topics, stored = false}).
|
||||||
|
|
||||||
|
-ifdef(TEST).
|
||||||
|
-compile(export_all).
|
||||||
|
-endif.
|
||||||
|
|
||||||
load(Opts) ->
|
load(Opts) ->
|
||||||
Topics = [{list_to_binary(Topic), Qos} || {Topic, Qos} <- Opts, 0 =< Qos, Qos =< 2],
|
Topics = [{bin(Topic), QoS} || {Topic, QoS} <- Opts, ?IS_QOS(QoS)],
|
||||||
|
State = #state{topics = Topics, stored = lists:member(stored, Opts)},
|
||||||
emqttd_broker:hook('client.connected', {?MODULE, client_connected},
|
emqttd_broker:hook('client.connected', {?MODULE, client_connected},
|
||||||
{?MODULE, client_connected, [Topics]}),
|
{?MODULE, client_connected, [State]}),
|
||||||
{ok, #state{topics = Topics}}.
|
{ok, State}.
|
||||||
|
|
||||||
client_connected(?CONNACK_ACCEPT, #mqtt_client{client_id = ClientId,
|
client_connected(?CONNACK_ACCEPT, #mqtt_client{client_id = ClientId,
|
||||||
client_pid = ClientPid,
|
client_pid = ClientPid,
|
||||||
username = Username}, Topics) ->
|
username = Username},
|
||||||
F = fun(Topic) ->
|
#state{topics = Topics, stored = Stored}) ->
|
||||||
Topic1 = emqttd_topic:feed_var(<<"$c">>, ClientId, Topic),
|
Replace = fun(Topic) -> rep(<<"$u">>, Username, rep(<<"$c">>, ClientId, Topic)) end,
|
||||||
if
|
TopicTable = with_stored(Stored, ClientId, [{Replace(Topic), Qos} || {Topic, Qos} <- Topics]),
|
||||||
Username =:= undefined -> Topic1;
|
emqttd_client:subscribe(ClientPid, TopicTable).
|
||||||
true -> emqttd_topic:feed_var(<<"$u">>, Username, Topic1)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
emqttd_client:subscribe(ClientPid, [{F(Topic), Qos} || {Topic, Qos} <- Topics]);
|
|
||||||
|
|
||||||
client_connected(_ConnAck, _Client, _Topics) ->
|
with_stored(false, _ClientId, TopicTable) ->
|
||||||
ignore.
|
TopicTable;
|
||||||
|
with_stored(true, ClientId, TopicTable) ->
|
||||||
|
Fun = fun(#mqtt_subscription{topic = Topic, qos = Qos}) -> {Topic, Qos} end,
|
||||||
|
emqttd_opts:merge([Fun(Sub) || Sub <- emqttd_pubsub:lookup(subscription, ClientId)], TopicTable).
|
||||||
|
|
||||||
unload(_Opts) ->
|
unload(_Opts) ->
|
||||||
emqttd_broker:unhook('client.connected', {?MODULE, client_connected}).
|
emqttd_broker:unhook('client.connected', {?MODULE, client_connected}).
|
||||||
|
|
||||||
|
rep(<<"$c">>, ClientId, Topic) ->
|
||||||
|
emqttd_topic:feed_var(<<"$c">>, ClientId, Topic);
|
||||||
|
rep(<<"$u">>, undefined, Topic) ->
|
||||||
|
Topic;
|
||||||
|
rep(<<"$u">>, Username, Topic) ->
|
||||||
|
emqttd_topic:feed_var(<<"$u">>, Username, Topic).
|
||||||
|
|
||||||
|
bin(B) when is_binary(B) ->
|
||||||
|
B;
|
||||||
|
bin(S) when is_list(S) ->
|
||||||
|
list_to_binary(S).
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
-module(emqttd_mod_subscription_tests).
|
||||||
|
|
||||||
|
-include("emqttd.hrl").
|
||||||
|
|
||||||
|
-ifdef(TEST).
|
||||||
|
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
|
-define(M, emqttd_mod_subscription).
|
||||||
|
|
||||||
|
rep_test() ->
|
||||||
|
?assertEqual(<<"topic/clientId">>, ?M:rep(<<"$c">>, <<"clientId">>, <<"topic/$c">>)),
|
||||||
|
?assertEqual(<<"topic/username">>, ?M:rep(<<"$u">>, <<"username">>, <<"topic/$u">>)),
|
||||||
|
?assertEqual(<<"topic/username/clientId">>,
|
||||||
|
?M:rep(<<"$c">>, <<"clientId">>,
|
||||||
|
?M:rep(<<"$u">>, <<"username">>, <<"topic/$u/$c">>))).
|
||||||
|
|
||||||
|
-endif.
|
Loading…
Reference in New Issue