commit
6ddfb7f2cb
|
@ -1,15 +1,17 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICZTCCAc4CCQCPzzI1ezeZPTANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQGEwJD
|
||||
TjERMA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91MREwDwYDVQQK
|
||||
EwhlbXF0dC5pbzERMA8GA1UEAxMIZW1xdHQuaW8xHDAaBgkqhkiG9w0BCQEWDWhv
|
||||
bmdAZW1xdHQuaW8wHhcNMTYxMDEzMDkwNzQ5WhcNMTYxMTEyMDkwNzQ5WjB3MQsw
|
||||
CQYDVQQGEwJDTjERMA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91
|
||||
MREwDwYDVQQKEwhlbXF0dC5pbzERMA8GA1UEAxMIZW1xdHQuaW8xHDAaBgkqhkiG
|
||||
9w0BCQEWDWhvbmdAZW1xdHQuaW8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
|
||||
AJ/6ACaLPXP6wpGOqc9+jFRFN6ufODqGB5SamCNmOKXpSm/U+KT87NPg4i4wn31s
|
||||
167nb65lk3IbdvzPzTSCAP6DG5s0+qDgpEMHeKKEC4zaAwoIxCgVUjab51RbVFBs
|
||||
AhzowxdRl6jQrGVgvXiLzz1+3b+1Xydu5J5Z2IeLm8NPAgMBAAEwDQYJKoZIhvcN
|
||||
AQEFBQADgYEAkt/VWi4tUUEdOnDwnCZ4IheV9Sp+6T3XsRxje7PKDsvZQlmpvMP6
|
||||
StfM+wkxty2dxVOU5Sx8CwXk5roKvULQY5rAyn9log6vEAI4Oyr4vnRN24JF7/Tr
|
||||
xeP1cOv2LJlEuQm1JWe+VtNqfJ+f81CnfaJMAo17W5T/5UxI5n8ziKc=
|
||||
MIICxjCCAa6gAwIBAgIJAPhU8tv3KMe/MA0GCSqGSIb3DQEBCwUAMBMxETAPBgNV
|
||||
BAMMCE15VGVzdENBMB4XDTE2MTAzMTA3MTU0NVoXDTE3MTAzMTA3MTU0NVowEzER
|
||||
MA8GA1UEAwwITXlUZXN0Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||
AQCtPcDnmjiVl7ScDhYvGaW+PUgfp7P5cM39mnrW6fkxhA0tgunWpWlYVKbcuh5y
|
||||
4bTNYrOQpcFO3Zg62tva4XEL8O1huqTlGsAeysZ3vWE4/8NGN/3wZy0TKDvwiwOB
|
||||
tbS3C5wcRQZohExL6yEL4XzDGk44x2mIs8/NzeG7Zycqybh9tsCJiHbLiTxnLa24
|
||||
v5USOtlvWye0hA0yUUqc2k7tKVmIMT4A4ulMb2sDVRrSLjyFDTI0c8grlPLfKbG8
|
||||
gpYLsHn9aAjqviyvmJdRLxwauqn+ghNWn1TyZwgAUxpoTtWeC0ilzEt18RP8vZjm
|
||||
eCbEP4qQDDvSCdLrie5CezyxAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0P
|
||||
BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQBJ/I/QJjU+mgkIaaHImFcIYFrfBirC
|
||||
vDiWo2W+zRh7CbcSf+jsksI99d230ixSDY36CPLKZeZhELST7xWKEELKbPdNbtOO
|
||||
EM10+XteLSXKVNGXfrEbW973eum3FGLobMA9OcH6+qDaf08pibe7kuv10aAgSs/I
|
||||
0Qg5H/UTAKQJKO9hhOgERM/FettuF+WGJaaZZZb9Y2YYBNRf/GtM8KHCjpCX9+XD
|
||||
kdeQGO8Hn10H9tOmggyfdIpsunBcs2/6/exCp8RPBWurN2GSW2RcnS5xVL0r+SVW
|
||||
VOhSDy1JwnNPczpqkqE74qAbAah0dTJFcFWzeGLVk7Kp+2pissAiU3gg
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICITCCAYoCCQDvPT34GnhwdzANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQGEwJD
|
||||
TjERMA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91MREwDwYDVQQK
|
||||
EwhlbXF0dC5pbzERMA8GA1UEAxMIZW1xdHQuaW8xHDAaBgkqhkiG9w0BCQEWDWhv
|
||||
bmdAZW1xdHQuaW8wHhcNMTYxMDEzMDkxNTMxWhcNMTYxMTEyMDkxNTMxWjB3MQsw
|
||||
CQYDVQQGEwJDTjERMA8GA1UECBMIWmhlSmlhbmcxETAPBgNVBAcTCEhhbmdaaG91
|
||||
MREwDwYDVQQKEwhlbXF0dC5pbzERMA8GA1UEAxMIZW1xdHQuaW8xHDAaBgkqhkiG
|
||||
9w0BCQEWDWhvbmdAZW1xdHQuaW8wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAx1yF
|
||||
I3YnvDPtHpGzJ+9ZGnnKkvMdaoyawT9rPvLsteeDkfknJcGCV5mKmjvH1xeeMIN1
|
||||
Kql9nVPoe7BtzJ0XwQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAALulKuZuE6RhwIT
|
||||
JBrUN7j4dbJe7Ttz+Q3qSQq6hNJoDf8hNrAHUDQzov9yU/KMMi9xE6+hu+ieuTo6
|
||||
hKLBDAD4hDzb6+EU5HAcASDkAXWnQq/Keo73+VrmUwMQs93tTC/jGXpsj/gLMEWB
|
||||
xcxXpgBPDGIR9L8Y2YMhEBLjm7Zv
|
||||
MIIC9jCCAd6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhNeVRl
|
||||
c3RDQTAeFw0xNjEwMzEwNzE1NDZaFw0xNzEwMzEwNzE1NDZaMDkxJjAkBgNVBAMT
|
||||
HWRlbmdoYWlndWlkZU1hY0Jvb2stQWlyLmxvY2FsMQ8wDQYDVQQKEwZjbGllbnQw
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmPMkieMtJO4PGIQG30uxI
|
||||
SEoRJoF2w0ufFhZGYCEaqFlHaSoc6nTiCUmnxadDpjkNBs4R6RDfM9zPJ0QdgSFO
|
||||
OJsWgQEHym/EQTcEx11+/2NDZWMJyZdpWZlU57SwHfWDwYa2XFX1bV+pAvhB8cli
|
||||
wCkygTwp1cZcwQpb8TfZySy8r5mwrWq2nhCQPtYqMxjNjpR/UeeZzt+Uh3CEXQ8h
|
||||
omjGinDXnnGwrYwBEP9G6fzTvyCWTyrsWC1Q37oAMzbkwFRoIBSAQWXBv9hgI08s
|
||||
IBYvXnRGKWOJZGxAP4a4TvpFS+nqi+fFVn4ktUfcH3PoSMh7PKavrFT2hQaryLt1
|
||||
AgMBAAGjLzAtMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsG
|
||||
AQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQAeimI8AQBFWiE9/Nf/0radux355mod
|
||||
5vPLbKn6I6nzb/sS/Ug8SMoFnkhncwj+XOgTSliUyWcwOB11UDVJbUIkB/x+Qo3w
|
||||
hvrATTdby2WdFNQvH4X7PmP8asDDN7ZxoLyRmuhjL4avJ3giwRcuQK4cB35b+Lb2
|
||||
p1e7hW81RaV7OEc0o4/vJgPvv9N7wvUuipwJns6PrN7VDn99lT8zWrt2pQ06e2mk
|
||||
jDuXulVpiUtLHJhTnABkCaKiHWCYAFfMjFeRb3gUXKqShzOyDSGWY91YMID/HE4r
|
||||
sVLm2mD1zurue8EmYtQQ6uiJIW9SzvshMHG6EA5QWA1ytoalfePbvf+c
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,9 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
|
|
@ -1,15 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
|
35
etc/emq.conf
35
etc/emq.conf
|
@ -169,37 +169,6 @@ mqtt.plugins.etc_dir = etc/plugins/
|
|||
## File to store loaded plugin names.
|
||||
mqtt.plugins.loaded_file = data/loaded_plugins
|
||||
|
||||
##-------------------------------------------------------------------
|
||||
## MQTT Modules
|
||||
##-------------------------------------------------------------------
|
||||
|
||||
## Enable retainer module
|
||||
mqtt.module.retainer = on
|
||||
|
||||
## disc: disc_copies, ram: ram_copies
|
||||
mqtt.module.retainer.storage_type = ram
|
||||
|
||||
## Max number of retained messages
|
||||
mqtt.module.retainer.max_message_num = 100000
|
||||
|
||||
## Max Payload Size of retained message
|
||||
mqtt.module.retainer.max_payload_size = 64KB
|
||||
|
||||
## Expired after seconds, never expired if 0
|
||||
mqtt.module.retainer.expired_after = 0
|
||||
|
||||
## Enable presence module
|
||||
## Publish presence messages when client connected or disconnected.
|
||||
mqtt.module.presence = on
|
||||
|
||||
mqtt.module.presence.qos = 0
|
||||
|
||||
## Enable subscription module
|
||||
## Subscribe topics automatically when client connected
|
||||
mqtt.module.subscription = on
|
||||
|
||||
mqtt.module.subscription.topics = $client/%c=1,$user/%u=1
|
||||
|
||||
##--------------------------------------------------------------------
|
||||
## MQTT Listeners
|
||||
##--------------------------------------------------------------------
|
||||
|
@ -237,10 +206,10 @@ mqtt.listener.ssl.max_clients = 512
|
|||
|
||||
## Configuring SSL Options
|
||||
## See http://erlang.org/doc/man/ssl.html
|
||||
mqtt.listener.ssl.handshake_timeout = 15
|
||||
mqtt.listener.ssl.handshake_timeout = 2000
|
||||
mqtt.listener.ssl.keyfile = etc/certs/key.pem
|
||||
mqtt.listener.ssl.certfile = etc/certs/cert.pem
|
||||
mqtt.listener.ssl.cacertfile = etc/certs/cacert.pem
|
||||
## mqtt.listener.ssl.cacertfile = etc/certs/cacert.pem
|
||||
## mqtt.listener.ssl.verify = verify_peer
|
||||
## mqtt.listener.ssl.failed_if_no_peer_cert = true
|
||||
|
||||
|
|
|
@ -55,6 +55,17 @@
|
|||
|
||||
-type(mqtt_topic() :: #mqtt_topic{}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% MQTT Subscription
|
||||
%%--------------------------------------------------------------------
|
||||
-record(mqtt_subscription, {
|
||||
subid :: binary() | atom(),
|
||||
topic :: binary(),
|
||||
qos :: 0 | 1 | 2
|
||||
}).
|
||||
|
||||
-type(mqtt_subscription() :: #mqtt_subscription{}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% MQTT Client
|
||||
%%--------------------------------------------------------------------
|
||||
|
|
|
@ -533,7 +533,7 @@ end}.
|
|||
]}.
|
||||
|
||||
{mapping, "mqtt.listener.ssl.verify", "emqttd.listeners", [
|
||||
{datatype, string}
|
||||
{datatype, atom}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.listener.ssl.failed_if_no_peer_cert", "emqttd.listeners", [
|
||||
|
@ -589,7 +589,7 @@ end}.
|
|||
]}.
|
||||
|
||||
{mapping, "mqtt.listener.https.verify", "emqttd.listeners", [
|
||||
{datatype, string}
|
||||
{datatype, atom}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.listener.https.failed_if_no_peer_cert", "emqttd.listeners", [
|
||||
|
@ -615,8 +615,8 @@ end}.
|
|||
{keyfile, cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)},
|
||||
{certfile, cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)},
|
||||
{cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)},
|
||||
{verify, cuttlefish:conf_get(Prefix ++ ".verify_peer", Conf, undefined)},
|
||||
{failed_if_no_peer_cert, cuttlefish:conf_get(Prefix ++ "failed_if_no_peer_cert", Conf, undefined)}])
|
||||
{verify, cuttlefish:conf_get(Prefix ++ ".verify", Conf, undefined)},
|
||||
{failed_if_no_peer_cert, cuttlefish:conf_get(Prefix ++ ".failed_if_no_peer_cert", Conf, undefined)}])
|
||||
end,
|
||||
|
||||
Listeners = fun(Name) when is_atom(Name) ->
|
||||
|
@ -636,83 +636,6 @@ end}.
|
|||
lists:append([Listeners(tcp), Listeners(ssl), Listeners(http), Listeners(https)])
|
||||
end}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% MQTT Modules
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
{mapping, "mqtt.module.retainer", "emqttd.modules", [
|
||||
{default, on},
|
||||
{datatype, flag}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.module.retainer.storage_type", "emqttd.modules", [
|
||||
{default, ram},
|
||||
{datatype, {enum, [disc, ram]}}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.module.retainer.max_message_num", "emqttd.modules", [
|
||||
{default, 100000},
|
||||
{datatype, integer}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.module.retainer.max_payload_size", "emqttd.modules", [
|
||||
{default, "64KB"},
|
||||
{datatype, bytesize}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.module.retainer.expired_after", "emqttd.modules", [
|
||||
{default, 0},
|
||||
{datatype, integer}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.module.presence", "emqttd.modules", [
|
||||
{default, on},
|
||||
{datatype, flag}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.module.presence.qos", "emqttd.modules", [
|
||||
{default, 0},
|
||||
{datatype, integer},
|
||||
{validators, ["range:0-2"]}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.module.subscription", "emqttd.modules", [
|
||||
{default, off},
|
||||
{datatype, flag}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.module.subscription.topics", "emqttd.modules", [
|
||||
{default, undefined},
|
||||
{datatype, string}
|
||||
]}.
|
||||
|
||||
{translation, "emqttd.modules", fun(Conf) ->
|
||||
WithMod = fun(Name, OptsF) ->
|
||||
Key = "mqtt.module." ++ atom_to_list(Name),
|
||||
case cuttlefish:conf_get(Key, Conf, false) of
|
||||
true -> [{Name, OptsF(Key)}];
|
||||
false -> []
|
||||
end
|
||||
end,
|
||||
RetainOpts = fun(Prefix) ->
|
||||
[{storage_type, cuttlefish:conf_get(Prefix ++ ".storage_type", Conf, ram)},
|
||||
{max_message_num, cuttlefish:conf_get(Prefix ++ ".max_message_num", Conf, undefined)},
|
||||
{max_payload_size, cuttlefish:conf_get(Prefix ++ ".max_payload_size", Conf, undefined)},
|
||||
{expired_after, cuttlefish:conf_get(Prefix ++ ".expired_after", Conf, 0)}]
|
||||
end,
|
||||
PresOpts = fun(Prefix) ->
|
||||
[{qos, cuttlefish:conf_get(Prefix ++ ".qos", Conf, 0)}]
|
||||
end,
|
||||
ParseFun = fun(undefined) -> [];
|
||||
(Topics) -> [begin
|
||||
[Topic, Qos] = string:tokens(S, "="),
|
||||
{list_to_binary(Topic), list_to_integer(Qos)}
|
||||
end || S <- string:tokens(Topics, ",")]
|
||||
end,
|
||||
SubOpts = fun(Prefix) -> ParseFun(cuttlefish:conf_get(Prefix ++ ".topics", Conf)) end,
|
||||
lists:append([WithMod(retainer, RetainOpts), WithMod(presence, PresOpts), WithMod(subscription, SubOpts)])
|
||||
end}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% System Monitor
|
||||
%%--------------------------------------------------------------------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{deps, [
|
||||
{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager","master"}},{gen_logger,".*",{git,"https://github.com/emqtt/gen_logger",""}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}},{getopt,".*",{git,"https://github.com/jcomellas/getopt","v0.8.2"}},{pbkdf2,".*",{git,"https://github.com/basho/erlang-pbkdf2","2.0.0"}},{clique,".*",{git,"https://github.com/basho/clique",""}},{time_compat,".*",{git,"https://github.com/lasp-lang/time_compat",""}},{rand_compat,".*",{git,"https://github.com/lasp-lang/rand_compat",""}}
|
||||
{gproc,".*",{git,"https://github.com/uwiger/gproc",""}},{lager,".*",{git,"https://github.com/basho/lager","master"}},{gen_logger,".*",{git,"https://github.com/emqtt/gen_logger",""}},{esockd,".*",{git,"https://github.com/emqtt/esockd","emq20"}},{mochiweb,".*",{git,"https://github.com/emqtt/mochiweb",""}}
|
||||
]}.
|
||||
{erl_opts, [{parse_transform,lager_transform}]}.
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
%% Application callbacks
|
||||
-export([start/2, stop/1]).
|
||||
|
||||
-export([start_listener/1, stop_listener/1, is_mod_enabled/1]).
|
||||
-export([start_listener/1, stop_listener/1]).
|
||||
|
||||
%% MQTT SockOpts
|
||||
-define(MQTT_SOCKOPTS, [binary, {packet, raw}, {reuseaddr, true},
|
||||
|
@ -47,7 +47,6 @@ start(_StartType, _StartArgs) ->
|
|||
start_servers(Sup),
|
||||
emqttd_cli:load(),
|
||||
register_acl_mod(),
|
||||
load_all_mods(),
|
||||
emqttd_plugins:init(),
|
||||
emqttd_plugins:load(),
|
||||
start_listeners(),
|
||||
|
@ -151,26 +150,6 @@ register_acl_mod() ->
|
|||
undefined -> ok
|
||||
end.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Load Modules
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% @doc Load all modules
|
||||
load_all_mods() ->
|
||||
lists:foreach(fun load_mod/1, emqttd:env(modules, [])).
|
||||
|
||||
load_mod({Name, Opts}) ->
|
||||
Mod = list_to_atom("emqttd_mod_" ++ atom_to_list(Name)),
|
||||
case catch Mod:load(Opts) of
|
||||
ok -> lager:info("Load module ~s successfully", [Name]);
|
||||
{error, Error} -> lager:error("Load module ~s error: ~p", [Name, Error]);
|
||||
{'EXIT', Reason} -> lager:error("Load module ~s error: ~p", [Name, Reason])
|
||||
end.
|
||||
|
||||
%% @doc Is module enabled?
|
||||
-spec(is_mod_enabled(Name :: atom()) -> boolean()).
|
||||
is_mod_enabled(Name) -> lists:keyfind(Name, 1, emqttd:env(modules, [])).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Start Listeners
|
||||
%%--------------------------------------------------------------------
|
||||
|
@ -231,11 +210,4 @@ merge_sockopts_test_() ->
|
|||
Opts = [{acceptors, 16}, {max_clients, 512}],
|
||||
?_assert(merge_sockopts(Opts) == [{sockopts, ?MQTT_SOCKOPTS} | Opts]).
|
||||
|
||||
load_all_mods_test_() ->
|
||||
?_assert(load_all_mods() == ok).
|
||||
|
||||
is_mod_enabled_test_() ->
|
||||
?_assert(is_mod_enabled(presence) == {module, presence, [{qos, 0}]}),
|
||||
?_assert(is_mod_enabled(test) == false).
|
||||
|
||||
-endif.
|
||||
|
|
|
@ -133,7 +133,8 @@ authorized(Req) ->
|
|||
false;
|
||||
"Basic " ++ BasicAuth ->
|
||||
{Username, Password} = user_passwd(BasicAuth),
|
||||
case emqttd_access_control:auth(#mqtt_client{username = Username}, Password) of
|
||||
{ok, Peer} = Req:get(peername),
|
||||
case emqttd_access_control:auth(#mqtt_client{username = Username, peername = Peer}, Password) of
|
||||
ok ->
|
||||
true;
|
||||
{error, Reason} ->
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqttd_mod_presence).
|
||||
|
||||
-behaviour(emqttd_gen_mod).
|
||||
|
||||
-include("emqttd.hrl").
|
||||
|
||||
-export([load/1, unload/1]).
|
||||
|
||||
-export([on_client_connected/3, on_client_disconnected/3]).
|
||||
|
||||
load(Opts) ->
|
||||
emqttd:hook('client.connected', fun ?MODULE:on_client_connected/3, [Opts]),
|
||||
emqttd:hook('client.disconnected', fun ?MODULE:on_client_disconnected/3, [Opts]).
|
||||
|
||||
on_client_connected(ConnAck, Client = #mqtt_client{client_id = ClientId,
|
||||
username = Username,
|
||||
peername = {IpAddr, _},
|
||||
clean_sess = CleanSess,
|
||||
proto_ver = ProtoVer}, Opts) ->
|
||||
Json = mochijson2:encode([{clientid, ClientId},
|
||||
{username, Username},
|
||||
{ipaddress, list_to_binary(emqttd_net:ntoa(IpAddr))},
|
||||
{session, sess(CleanSess)},
|
||||
{protocol, ProtoVer},
|
||||
{connack, ConnAck},
|
||||
{ts, emqttd_time:now_to_secs()}]),
|
||||
Msg = message(qos(Opts), topic(connected, ClientId), Json),
|
||||
emqttd:publish(emqttd_message:set_flag(sys, Msg)),
|
||||
{ok, Client}.
|
||||
|
||||
on_client_disconnected(Reason, #mqtt_client{client_id = ClientId}, Opts) ->
|
||||
Json = mochijson2:encode([{clientid, ClientId},
|
||||
{reason, reason(Reason)},
|
||||
{ts, emqttd_time:now_to_secs()}]),
|
||||
Msg = message(qos(Opts), topic(disconnected, ClientId), Json),
|
||||
emqttd:publish(emqttd_message:set_flag(sys, Msg)),
|
||||
ok.
|
||||
|
||||
unload(_Opts) ->
|
||||
emqttd:unhook('client.connected', fun ?MODULE:on_client_connected/3),
|
||||
emqttd:unhook('client.disconnected', fun ?MODULE:on_client_disconnected/3).
|
||||
|
||||
sess(false) -> true;
|
||||
sess(true) -> false.
|
||||
|
||||
qos(Opts) -> proplists:get_value(qos, Opts, 0).
|
||||
|
||||
message(Qos, Topic, Json) ->
|
||||
emqttd_message:make(presence, Qos, Topic, iolist_to_binary(Json)).
|
||||
|
||||
topic(connected, ClientId) ->
|
||||
emqttd_topic:systop(list_to_binary(["clients/", ClientId, "/connected"]));
|
||||
topic(disconnected, ClientId) ->
|
||||
emqttd_topic:systop(list_to_binary(["clients/", ClientId, "/disconnected"])).
|
||||
|
||||
reason(Reason) when is_atom(Reason) -> Reason;
|
||||
reason({Error, _}) when is_atom(Error) -> Error;
|
||||
reason(_) -> internal_error.
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqttd_mod_retainer).
|
||||
|
||||
-behaviour(gen_server).
|
||||
|
||||
-behaviour(emqttd_gen_mod).
|
||||
|
||||
-include("emqttd.hrl").
|
||||
|
||||
-include("emqttd_internal.hrl").
|
||||
|
||||
-include_lib("stdlib/include/ms_transform.hrl").
|
||||
|
||||
%% gen_mod Callbacks
|
||||
-export([load/1, unload/1]).
|
||||
|
||||
%% Hook Callbacks
|
||||
-export([on_session_subscribed/4, on_message_publish/2]).
|
||||
|
||||
%% API Function Exports
|
||||
-export([start_link/1]).
|
||||
|
||||
%% gen_server Function Exports
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
-record(mqtt_retained, {topic, msg}).
|
||||
|
||||
-record(state, {stats_fun, expired_after, stats_timer, expire_timer}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Load/Unload
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
load(Env) ->
|
||||
emqttd_mod_sup:start_child(spec(Env)),
|
||||
emqttd:hook('session.subscribed', fun ?MODULE:on_session_subscribed/4, [Env]),
|
||||
emqttd:hook('message.publish', fun ?MODULE:on_message_publish/2, [Env]).
|
||||
|
||||
on_session_subscribed(_ClientId, _Username, {Topic, _Opts}, _Env) ->
|
||||
SessPid = self(),
|
||||
Msgs = case emqttd_topic:wildcard(Topic) of
|
||||
false -> read_messages(Topic);
|
||||
true -> match_messages(Topic)
|
||||
end,
|
||||
lists:foreach(fun(Msg) -> SessPid ! {dispatch, Topic, Msg} end, lists:reverse(Msgs)).
|
||||
|
||||
on_message_publish(Msg = #mqtt_message{retain = false}, _Env) ->
|
||||
{ok, Msg};
|
||||
|
||||
%% RETAIN flag set to 1 and payload containing zero bytes
|
||||
on_message_publish(Msg = #mqtt_message{retain = true, topic = Topic, payload = <<>>}, _Env) ->
|
||||
mnesia:dirty_delete(mqtt_retained, Topic),
|
||||
{stop, Msg};
|
||||
|
||||
on_message_publish(Msg = #mqtt_message{topic = Topic, retain = true, payload = Payload}, Env) ->
|
||||
case {is_table_full(Env), is_too_big(size(Payload), Env)} of
|
||||
{false, false} ->
|
||||
mnesia:dirty_write(#mqtt_retained{topic = Topic, msg = Msg}),
|
||||
emqttd_metrics:set('messages/retained', retained_count());
|
||||
{true, _}->
|
||||
lager:error("Cannot retain message(topic=~s) for table is full!", [Topic]);
|
||||
{_, true}->
|
||||
lager:error("Cannot retain message(topic=~s, payload_size=~p)"
|
||||
" for payload is too big!", [Topic, size(Payload)])
|
||||
end,
|
||||
{ok, Msg#mqtt_message{retain = false}}.
|
||||
|
||||
is_table_full(Env) ->
|
||||
Limit = proplists:get_value(max_message_num, Env, 0),
|
||||
Limit > 0 andalso (retained_count() > Limit).
|
||||
|
||||
is_too_big(Size, Env) ->
|
||||
Limit = proplists:get_value(max_payload_size, Env, 0),
|
||||
Limit > 0 andalso (Size > Limit).
|
||||
|
||||
unload(_Env) ->
|
||||
emqttd:unhook('session.subscribed', fun ?MODULE:on_session_subscribed/4),
|
||||
emqttd:unhook('message.publish', fun ?MODULE:on_message_publish/2),
|
||||
emqttd_mod_sup:stop_child(?MODULE).
|
||||
|
||||
spec(Env) ->
|
||||
{?MODULE, {?MODULE, start_link, [Env]}, permanent, 5000, worker, [?MODULE]}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% API
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% @doc Start the retainer
|
||||
-spec(start_link(Env :: list()) -> {ok, pid()} | ignore | {error, any()}).
|
||||
start_link(Env) ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [Env], []).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% gen_server Callbacks
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
init([Env]) ->
|
||||
Copy = case proplists:get_value(storage_type, Env, disc) of
|
||||
disc -> disc_copies;
|
||||
ram -> ram_copies
|
||||
end,
|
||||
ok = emqttd_mnesia:create_table(mqtt_retained, [
|
||||
{type, ordered_set},
|
||||
{Copy, [node()]},
|
||||
{record_name, mqtt_retained},
|
||||
{attributes, record_info(fields, mqtt_retained)},
|
||||
{storage_properties, [{ets, [compressed]},
|
||||
{dets, [{auto_save, 1000}]}]}]),
|
||||
ok = emqttd_mnesia:copy_table(mqtt_retained),
|
||||
StatsFun = emqttd_stats:statsfun('retained/count', 'retained/max'),
|
||||
{ok, StatsTimer} = timer:send_interval(timer:seconds(1), stats),
|
||||
State = #state{stats_fun = StatsFun, stats_timer = StatsTimer},
|
||||
{ok, init_expire_timer(proplists:get_value(expired_after, Env, 0), State)}.
|
||||
|
||||
init_expire_timer(0, State) ->
|
||||
State;
|
||||
init_expire_timer(undefined, State) ->
|
||||
State;
|
||||
init_expire_timer(Secs, State) ->
|
||||
{ok, Timer} = timer:send_interval(timer:seconds(Secs), expire),
|
||||
State#state{expired_after = Secs, expire_timer = Timer}.
|
||||
|
||||
handle_call(Req, _From, State) ->
|
||||
?UNEXPECTED_REQ(Req, State).
|
||||
|
||||
handle_cast(Msg, State) ->
|
||||
?UNEXPECTED_MSG(Msg, State).
|
||||
|
||||
handle_info(stats, State = #state{stats_fun = StatsFun}) ->
|
||||
StatsFun(retained_count()),
|
||||
{noreply, State, hibernate};
|
||||
|
||||
handle_info(expire, State = #state{expired_after = Never})
|
||||
when Never =:= 0 orelse Never =:= undefined ->
|
||||
{noreply, State, hibernate};
|
||||
|
||||
handle_info(expire, State = #state{expired_after = ExpiredAfter}) ->
|
||||
expire_messages(emqttd_time:now_to_secs() - ExpiredAfter),
|
||||
{noreply, State, hibernate};
|
||||
|
||||
handle_info(Info, State) ->
|
||||
?UNEXPECTED_INFO(Info, State).
|
||||
|
||||
terminate(_Reason, _State = #state{stats_timer = TRef1, expire_timer = TRef2}) ->
|
||||
timer:cancel(TRef1),
|
||||
timer:cancel(TRef2).
|
||||
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
{ok, State}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Internal Functions
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec(read_messages(binary()) -> [mqtt_message()]).
|
||||
read_messages(Topic) ->
|
||||
[Msg || #mqtt_retained{msg = Msg} <- mnesia:dirty_read(mqtt_retained, Topic)].
|
||||
|
||||
-spec(match_messages(binary()) -> [mqtt_message()]).
|
||||
match_messages(Filter) ->
|
||||
%% TODO: optimize later...
|
||||
Fun = fun(#mqtt_retained{topic = Name, msg = Msg}, Acc) ->
|
||||
case emqttd_topic:match(Name, Filter) of
|
||||
true -> [Msg|Acc];
|
||||
false -> Acc
|
||||
end
|
||||
end,
|
||||
mnesia:async_dirty(fun mnesia:foldl/3, [Fun, [], mqtt_retained]).
|
||||
|
||||
-spec(expire_messages(pos_integer()) -> any()).
|
||||
expire_messages(Time) when is_integer(Time) ->
|
||||
mnesia:transaction(
|
||||
fun() ->
|
||||
Match = ets:fun2ms(
|
||||
fun(#mqtt_retained{topic = Topic, msg = #mqtt_message{timestamp = Ts}})
|
||||
when Time > Ts -> Topic
|
||||
end),
|
||||
Topics = mnesia:select(mqtt_retained, Match, write),
|
||||
lists:foreach(fun(<<"$SYS/", _/binary>>) -> ok; %% ignore $SYS/# messages
|
||||
(Topic) -> mnesia:delete({mqtt_retained, Topic})
|
||||
end, Topics)
|
||||
end).
|
||||
|
||||
-spec(retained_count() -> non_neg_integer()).
|
||||
retained_count() -> mnesia:table_info(mqtt_retained, size).
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqttd_mod_subscription).
|
||||
|
||||
-behaviour(emqttd_gen_mod).
|
||||
|
||||
-include("emqttd.hrl").
|
||||
|
||||
-include("emqttd_protocol.hrl").
|
||||
|
||||
-export([load/1, on_client_connected/3, unload/1]).
|
||||
|
||||
load(Opts) ->
|
||||
Topics = [{iolist_to_binary(Topic), QoS} || {Topic, QoS} <- Opts, ?IS_QOS(QoS)],
|
||||
emqttd:hook('client.connected', fun ?MODULE:on_client_connected/3, [Topics]).
|
||||
|
||||
on_client_connected(?CONNACK_ACCEPT, Client = #mqtt_client{client_id = ClientId,
|
||||
client_pid = ClientPid,
|
||||
username = Username}, Topics) ->
|
||||
|
||||
Replace = fun(Topic) -> rep(<<"%u">>, Username, rep(<<"%c">>, ClientId, Topic)) end,
|
||||
TopicTable = [{Replace(Topic), Qos} || {Topic, Qos} <- Topics],
|
||||
emqttd_client:subscribe(ClientPid, TopicTable),
|
||||
{ok, Client};
|
||||
|
||||
on_client_connected(_ConnAck, _Client, _State) ->
|
||||
ok.
|
||||
|
||||
unload(_Opts) ->
|
||||
emqttd:unhook('client.connected', fun ?MODULE:on_client_connected/3).
|
||||
|
||||
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).
|
||||
|
|
@ -228,7 +228,7 @@ del_subscriber_(Share, Topic, Subscriber) ->
|
|||
|
||||
del_local_subscriber_(Share, Topic, Subscriber) ->
|
||||
ets:delete_object(mqtt_subscriber, {{local, Topic}, shared(Share, Subscriber)}),
|
||||
(not ets:member(subscriber, {local, Topic})) andalso emqttd_router:del_local_route(Topic).
|
||||
(not ets:member(mqtt_subscriber, {local, Topic})) andalso emqttd_router:del_local_route(Topic).
|
||||
|
||||
shared(undefined, Subscriber) ->
|
||||
Subscriber;
|
||||
|
|
|
@ -80,6 +80,9 @@ mqtt.client_idle_timeout = 30
|
|||
## Allow Anonymous authentication
|
||||
mqtt.allow_anonymous = true
|
||||
|
||||
## Default ACL File
|
||||
mqtt.acl_file = etc/acl.conf
|
||||
|
||||
##--------------------------------------------------------------------
|
||||
## MQTT Session
|
||||
##--------------------------------------------------------------------
|
||||
|
@ -161,10 +164,10 @@ mqtt.bridge.ping_down_interval = 1
|
|||
##-------------------------------------------------------------------
|
||||
|
||||
## Dir of plugins' config
|
||||
##mqtt.plugins.etc_dir = etc/plugins/
|
||||
mqtt.plugins.etc_dir = etc/plugins/
|
||||
|
||||
## File to store loaded plugin names.
|
||||
##mqtt.plugins.loaded_file = data/loaded_plugins
|
||||
mqtt.plugins.loaded_file = data/loaded_plugins
|
||||
|
||||
##-------------------------------------------------------------------
|
||||
## MQTT Modules
|
||||
|
@ -186,8 +189,7 @@ mqtt.module.retainer.max_payload_size = 64KB
|
|||
mqtt.module.retainer.expired_after = 0
|
||||
|
||||
## Enable presence module
|
||||
## Client presence management module. Publish presence messages when
|
||||
## client connected or disconnected.
|
||||
## Publish presence messages when client connected or disconnected.
|
||||
mqtt.module.presence = on
|
||||
|
||||
mqtt.module.presence.qos = 0
|
||||
|
@ -235,26 +237,26 @@ mqtt.listener.ssl.max_clients = 512
|
|||
|
||||
## Configuring SSL Options
|
||||
## See http://erlang.org/doc/man/ssl.html
|
||||
mqtt.listener.ssl.handshake_timeout = 15 #seconds
|
||||
mqtt.listener.ssl.keyfile = etc/ssl/key.pem
|
||||
mqtt.listener.ssl.certfile = etc/ssl/cert.pem
|
||||
mqtt.listener.ssl.cacertfile = etc/ssl/cacert.pem
|
||||
mqtt.listener.ssl.handshake_timeout = 15
|
||||
mqtt.listener.ssl.keyfile = etc/certs/key.pem
|
||||
mqtt.listener.ssl.certfile = etc/certs/cert.pem
|
||||
## mqtt.listener.ssl.cacertfile = etc/certs/cacert.pem
|
||||
## mqtt.listener.ssl.verify = verify_peer
|
||||
## mqtt.listener.ssl.failed_if_no_peer_cert = true
|
||||
|
||||
## HTTP Listener
|
||||
## HTTP and WebSocket Listener
|
||||
mqtt.listener.http = 8083
|
||||
mqtt.listener.http.acceptors = 4
|
||||
mqtt.listener.http.max_clients = 64
|
||||
|
||||
## HTTP(SSL) Listener
|
||||
mqtt.listener.https = 8084
|
||||
mqtt.listener.https.acceptors = 4
|
||||
mqtt.listener.https.max_clients = 64
|
||||
mqtt.listener.https.handshake_timeout = 10 #seconds
|
||||
mqtt.listener.https.certfile = etc/ssl/cert.pem
|
||||
mqtt.listener.https.keyfile = etc/ssl/key.pem
|
||||
mqtt.listener.https.cacertfile = etc/ssl/cacert.pem
|
||||
## mqtt.listener.https = 8084
|
||||
## mqtt.listener.https.acceptors = 4
|
||||
## mqtt.listener.https.max_clients = 64
|
||||
## mqtt.listener.https.handshake_timeout = 10
|
||||
## mqtt.listener.https.certfile = etc/certs/cert.pem
|
||||
## mqtt.listener.https.keyfile = etc/certs/key.pem
|
||||
## mqtt.listener.https.cacertfile = etc/certs/cacert.pem
|
||||
## mqtt.listener.https.verify = verify_peer
|
||||
## mqtt.listener.https.failed_if_no_peer_cert = true
|
||||
|
||||
|
|
|
@ -261,6 +261,12 @@ end}.
|
|||
hidden
|
||||
]}.
|
||||
|
||||
%% @doc Default ACL File
|
||||
{mapping, "mqtt.acl_file", "emqttd.acl_file", [
|
||||
{datatype, string},
|
||||
hidden
|
||||
]}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% MQTT Session
|
||||
%%--------------------------------------------------------------------
|
||||
|
@ -527,7 +533,7 @@ end}.
|
|||
]}.
|
||||
|
||||
{mapping, "mqtt.listener.ssl.verify", "emqttd.listeners", [
|
||||
{datatype, string}
|
||||
{datatype, atom}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.listener.ssl.failed_if_no_peer_cert", "emqttd.listeners", [
|
||||
|
@ -583,7 +589,7 @@ end}.
|
|||
]}.
|
||||
|
||||
{mapping, "mqtt.listener.https.verify", "emqttd.listeners", [
|
||||
{datatype, string}
|
||||
{datatype, atom}
|
||||
]}.
|
||||
|
||||
{mapping, "mqtt.listener.https.failed_if_no_peer_cert", "emqttd.listeners", [
|
||||
|
@ -609,8 +615,8 @@ end}.
|
|||
{keyfile, cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)},
|
||||
{certfile, cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)},
|
||||
{cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)},
|
||||
{verify, cuttlefish:conf_get(Prefix ++ ".verify_peer", Conf, undefined)},
|
||||
{failed_if_no_peer_cert, cuttlefish:conf_get(Prefix ++ "failed_if_no_peer_cert", Conf, undefined)}])
|
||||
{verify, cuttlefish:conf_get(Prefix ++ ".verify", Conf, undefined)},
|
||||
{failed_if_no_peer_cert, cuttlefish:conf_get(Prefix ++ ".failed_if_no_peer_cert", Conf, undefined)}])
|
||||
end,
|
||||
|
||||
Listeners = fun(Name) when is_atom(Name) ->
|
||||
|
@ -703,7 +709,7 @@ end}.
|
|||
{list_to_binary(Topic), list_to_integer(Qos)}
|
||||
end || S <- string:tokens(Topics, ",")]
|
||||
end,
|
||||
SubOpts = fun(Prefix) -> [{topics, ParseFun(cuttlefish:conf_get(Prefix ++ ".topics", Conf))}] end,
|
||||
SubOpts = fun(Prefix) -> ParseFun(cuttlefish:conf_get(Prefix ++ ".topics", Conf)) end,
|
||||
lists:append([WithMod(retainer, RetainOpts), WithMod(presence, PresOpts), WithMod(subscription, SubOpts)])
|
||||
end}.
|
||||
|
||||
|
|
Loading…
Reference in New Issue