Feng 10 лет назад
Родитель
Сommit
fe82fde717
2 измененных файлов с 53 добавлено и 19 удалено
  1. 35 19
      src/emqttd_mod_autosub.erl
  2. 18 0
      test/emqttd_mod_subscription_tests.erl

+ 35 - 19
src/emqttd_mod_autosub.erl

@@ -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]}),
-    {ok, #state{topics = Topics}}.
+                       {?MODULE, client_connected, [State]}),
+    {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) ->
-    F = fun(Topic) ->
-            Topic1 = emqttd_topic:feed_var(<<"$c">>, ClientId, Topic),
-            if
-                Username =:= undefined -> Topic1;
-                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) ->
-    ignore.
+                                               username   = Username},
+                 #state{topics = Topics, stored = Stored}) ->
+    Replace = fun(Topic) -> rep(<<"$u">>, Username, rep(<<"$c">>, ClientId, Topic)) end,
+    TopicTable = with_stored(Stored, ClientId, [{Replace(Topic), Qos} || {Topic, Qos} <- Topics]),
+    emqttd_client:subscribe(ClientPid, TopicTable).
+
+with_stored(false, _ClientId, TopicTable) ->
+    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).
+

+ 18 - 0
test/emqttd_mod_subscription_tests.erl

@@ -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.