Licensed under the Apache, Version 2.0

This commit is contained in:
Feng 2016-02-05 14:26:17 +08:00
parent 1e852ded91
commit 94c3e69b44
72 changed files with 1989 additions and 2825 deletions

214
LICENSE
View File

@ -1,25 +1,201 @@
The MIT License (MIT) Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (c) 2012-2016 eMQTT.IO, All Rights Reserved. TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Permission is hereby granted, free of charge, to any person obtaining a copy 1. Definitions.
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all "License" shall mean the terms and conditions for use, reproduction,
copies or substantial portions of the Software. and distribution as defined by Sections 1 through 9 of this document.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR "Licensor" shall mean the copyright owner or entity authorized by
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, the copyright owner that is granting the License.
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The source files 'gen_server2.erl' and 'priority_queue.erl' are from RabbitMQ "Legal Entity" shall mean the union of the acting entity and all
v3.5.4 and licensed under MPL license. other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.

View File

@ -145,5 +145,5 @@ Feng Lee <feng@emqtt.io>
## License ## License
The MIT License (MIT) Apache License Version 2.0

View File

@ -1,33 +1,25 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc
%%% MQTT Broker Header.
%%%
%%% @end
%%%-----------------------------------------------------------------------------
%%------------------------------------------------------------------------------ %% @doc MQTT Broker Header.
%%--------------------------------------------------------------------
%% Banner %% Banner
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-define(COPYRIGHT, "Copyright (C) 2012-2016, Feng Lee <feng@emqtt.io>"). -define(COPYRIGHT, "Copyright (C) 2012-2016, Feng Lee <feng@emqtt.io>").
-define(LICENSE_MESSAGE, "Licensed under MIT"). -define(LICENSE_MESSAGE, "Licensed under MIT").
@ -42,16 +34,17 @@
%% Queue Topics. %% Queue Topics.
-define(QTop, <<"$Q">>). -define(QTop, <<"$Q">>).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% PubSub %% PubSub
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-type pubsub() :: publish | subscribe. -type pubsub() :: publish | subscribe.
-define(IS_PUBSUB(PS), (PS =:= publish orelse PS =:= subscribe)). -define(IS_PUBSUB(PS), (PS =:= publish orelse PS =:= subscribe)).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Topic %% MQTT Topic
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-record(mqtt_topic, { -record(mqtt_topic, {
topic :: binary(), topic :: binary(),
node :: node() node :: node()
@ -59,24 +52,23 @@
-type mqtt_topic() :: #mqtt_topic{}. -type mqtt_topic() :: #mqtt_topic{}.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Subscription %% MQTT Subscription
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-record(mqtt_subscription, { -record(mqtt_subscription, {
subid :: binary() | atom(), subid :: binary() | atom(),
topic :: binary(), topic :: binary(),
qos = 0 :: 0 | 1 | 2, qos = 0 :: 0 | 1 | 2
static = false :: boolean()
}). }).
-type mqtt_subscription() :: #mqtt_subscription{}. -type mqtt_subscription() :: #mqtt_subscription{}.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Client %% MQTT Client
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-type header_key() :: atom() | binary() | string(). -type ws_header_key() :: atom() | binary() | string().
-type header_val() :: atom() | binary() | string() | integer(). -type ws_header_val() :: atom() | binary() | string() | integer().
-record(mqtt_client, { -record(mqtt_client, {
client_id :: binary() | undefined, client_id :: binary() | undefined,
@ -87,15 +79,15 @@
proto_ver :: 3 | 4, proto_ver :: 3 | 4,
keepalive = 0, keepalive = 0,
will_topic :: undefined | binary(), will_topic :: undefined | binary(),
ws_initial_headers :: list({header_key(), header_val()}), ws_initial_headers :: list({ws_header_key(), ws_header_val()}),
connected_at :: erlang:timestamp() connected_at :: erlang:timestamp()
}). }).
-type mqtt_client() :: #mqtt_client{}. -type mqtt_client() :: #mqtt_client{}.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Session %% MQTT Session
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-record(mqtt_session, { -record(mqtt_session, {
client_id :: binary(), client_id :: binary(),
sess_pid :: pid(), sess_pid :: pid(),
@ -104,9 +96,9 @@
-type mqtt_session() :: #mqtt_session{}. -type mqtt_session() :: #mqtt_session{}.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Message %% MQTT Message
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-type mqtt_msgid() :: binary() | undefined. -type mqtt_msgid() :: binary() | undefined.
-type mqtt_pktid() :: 1..16#ffff | undefined. -type mqtt_pktid() :: 1..16#ffff | undefined.
@ -127,9 +119,9 @@
-type mqtt_message() :: #mqtt_message{}. -type mqtt_message() :: #mqtt_message{}.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Alarm %% MQTT Alarm
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-record(mqtt_alarm, { -record(mqtt_alarm, {
id :: binary(), id :: binary(),
severity :: warning | error | critical, severity :: warning | error | critical,
@ -140,9 +132,9 @@
-type mqtt_alarm() :: #mqtt_alarm{}. -type mqtt_alarm() :: #mqtt_alarm{}.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Plugin %% MQTT Plugin
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-record(mqtt_plugin, { -record(mqtt_plugin, {
name, name,
version, version,
@ -153,10 +145,10 @@
-type mqtt_plugin() :: #mqtt_plugin{}. -type mqtt_plugin() :: #mqtt_plugin{}.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT CLI Command %% MQTT CLI Command
%% For example: 'broker metrics' %% For example: 'broker metrics'
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-record(mqtt_cli, { -record(mqtt_cli, {
name, name,
action, action,

View File

@ -1,24 +1,18 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 eMQTT.IO, All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
-define(PRINT(Format, Args), -define(PRINT(Format, Args),
io:format(Format, Args)). io:format(Format, Args)).

View File

@ -1,27 +1,20 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 eMQTT.IO, All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Internal Header File
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Internal Header File
%%%
%%%-----------------------------------------------------------------------------
-define(GPROC_POOL(JoinOrLeave, Pool, I), -define(GPROC_POOL(JoinOrLeave, Pool, I),
(begin (begin

View File

@ -1,33 +1,24 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% @Copyright (C) 2012-2016, Feng Lee <feng@emqtt.io> %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc
%%% MQTT Protocol Header.
%%%
%%% @end
%%%-----------------------------------------------------------------------------
%%------------------------------------------------------------------------------ %% @doc MQTT Protocol Header.
%%--------------------------------------------------------------------
%% MQTT Protocol Version and Levels %% MQTT Protocol Version and Levels
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-define(MQTT_PROTO_V31, 3). -define(MQTT_PROTO_V31, 3).
-define(MQTT_PROTO_V311, 4). -define(MQTT_PROTO_V311, 4).
@ -37,9 +28,9 @@
-type mqtt_vsn() :: ?MQTT_PROTO_V31 | ?MQTT_PROTO_V311. -type mqtt_vsn() :: ?MQTT_PROTO_V31 | ?MQTT_PROTO_V311.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT QoS %% MQTT QoS
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-define(QOS_0, 0). %% At most once -define(QOS_0, 0). %% At most once
-define(QOS_1, 1). %% At least once -define(QOS_1, 1). %% At least once
-define(QOS_2, 2). %% Exactly once -define(QOS_2, 2). %% Exactly once
@ -72,14 +63,14 @@
end). end).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% Max ClientId Length. Why 1024? NiDongDe! %% Max ClientId Length. Why 1024? NiDongDe...
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-define(MAX_CLIENTID_LEN, 1024). -define(MAX_CLIENTID_LEN, 1024).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Control Packet Types %% MQTT Control Packet Types
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-define(RESERVED, 0). %% Reserved -define(RESERVED, 0). %% Reserved
-define(CONNECT, 1). %% Client request to connect to Server -define(CONNECT, 1). %% Client request to connect to Server
-define(CONNACK, 2). %% Server to Client: Connect acknowledgment -define(CONNACK, 2). %% Server to Client: Connect acknowledgment
@ -114,9 +105,9 @@
-type mqtt_packet_type() :: ?RESERVED..?DISCONNECT. -type mqtt_packet_type() :: ?RESERVED..?DISCONNECT.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Connect Return Codes %% MQTT Connect Return Codes
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-define(CONNACK_ACCEPT, 0). %% Connection accepted -define(CONNACK_ACCEPT, 0). %% Connection accepted
-define(CONNACK_PROTO_VER, 1). %% Unacceptable protocol version -define(CONNACK_PROTO_VER, 1). %% Unacceptable protocol version
-define(CONNACK_INVALID_ID, 2). %% Client Identifier is correct UTF-8 but not allowed by the Server -define(CONNACK_INVALID_ID, 2). %% Client Identifier is correct UTF-8 but not allowed by the Server
@ -126,25 +117,25 @@
-type mqtt_connack() :: ?CONNACK_ACCEPT..?CONNACK_AUTH. -type mqtt_connack() :: ?CONNACK_ACCEPT..?CONNACK_AUTH.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Parser and Serialiser %% MQTT Parser and Serializer
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-define(MAX_LEN, 16#fffffff). -define(MAX_LEN, 16#fffffff).
-define(HIGHBIT, 2#10000000). -define(HIGHBIT, 2#10000000).
-define(LOWBITS, 2#01111111). -define(LOWBITS, 2#01111111).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Packet Fixed Header %% MQTT Packet Fixed Header
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-record(mqtt_packet_header, { -record(mqtt_packet_header, {
type = ?RESERVED :: mqtt_packet_type(), type = ?RESERVED :: mqtt_packet_type(),
dup = false :: boolean(), dup = false :: boolean(),
qos = ?QOS_0 :: mqtt_qos(), qos = ?QOS_0 :: mqtt_qos(),
retain = false :: boolean()}). retain = false :: boolean()}).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Packets %% MQTT Packets
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-type mqtt_client_id() :: binary(). -type mqtt_client_id() :: binary().
-type mqtt_packet_id() :: 1..16#ffff | undefined. -type mqtt_packet_id() :: 1..16#ffff | undefined.
@ -188,9 +179,9 @@
-record(mqtt_packet_unsuback, { -record(mqtt_packet_unsuback, {
packet_id :: mqtt_packet_id() }). packet_id :: mqtt_packet_id() }).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Control Packet %% MQTT Control Packet
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-record(mqtt_packet, { -record(mqtt_packet, {
header :: #mqtt_packet_header{}, header :: #mqtt_packet_header{},
variable :: #mqtt_packet_connect{} | #mqtt_packet_connack{} variable :: #mqtt_packet_connect{} | #mqtt_packet_connack{}
@ -202,9 +193,9 @@
-type mqtt_packet() :: #mqtt_packet{}. -type mqtt_packet() :: #mqtt_packet{}.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Packet Match %% MQTT Packet Match
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
-define(CONNECT_PACKET(Var), -define(CONNECT_PACKET(Var),
#mqtt_packet{header = #mqtt_packet_header{type = ?CONNECT}, variable = Var}). #mqtt_packet{header = #mqtt_packet_header{type = ?CONNECT}, variable = Var}).

View File

@ -1,8 +1,8 @@
{application, emqttd, {application, emqttd,
[ [
{id, "emqttd"},
{vsn, "0.15.1"},
{description, "Erlang MQTT Broker"}, {description, "Erlang MQTT Broker"},
{vsn, "0.16.0"},
{id, "emqttd"},
{modules, []}, {modules, []},
{registered, []}, {registered, []},
{applications, [kernel, {applications, [kernel,

View File

@ -1,38 +1,28 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd main module.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
%% @doc emqttd main module.
%% @author Feng Lee <feng@emqtt.io>
-module(emqttd). -module(emqttd).
-export([start/0, env/1, env/2, -export([start/0, env/1, env/2, start_listeners/0, stop_listeners/0,
start_listeners/0, stop_listeners/0, load_all_mods/0, is_mod_enabled/1, is_running/1]).
load_all_mods/0, is_mod_enabled/1,
is_running/1, seed_now/0]).
%% Utility functions. %% Utility functions.
-export([reg_name/2]). -export([reg_name/2, seed_now/0]).
-define(MQTT_SOCKOPTS, [ -define(MQTT_SOCKOPTS, [
binary, binary,
@ -45,86 +35,66 @@
-type listener() :: {atom(), inet:port_number(), [esockd:option()]}. -type listener() :: {atom(), inet:port_number(), [esockd:option()]}.
%%------------------------------------------------------------------------------
%% @doc Start emqttd application. %% @doc Start emqttd application.
%% @end
%%------------------------------------------------------------------------------
-spec start() -> ok | {error, any()}. -spec start() -> ok | {error, any()}.
start() -> start() -> application:start(?APP).
application:start(?APP).
%% @doc Group environment
-spec env(Group :: atom()) -> list().
env(Group) -> application:get_env(?APP, Group, []).
%%------------------------------------------------------------------------------
%% @doc Get environment %% @doc Get environment
%% @end -spec env(Group :: atom(), Name :: atom()) -> undefined | any().
%%------------------------------------------------------------------------------ env(Group, Name) -> proplists:get_value(Name, env(Group)).
-spec env(atom()) -> list().
env(Group) ->
application:get_env(?APP, Group, []).
-spec env(atom(), atom()) -> undefined | any(). %% @doc Start Listeners of the broker.
env(Group, Name) ->
proplists:get_value(Name, env(Group)).
%%------------------------------------------------------------------------------
%% @doc Start Listeners
%% @end
%%------------------------------------------------------------------------------
-spec start_listeners() -> any(). -spec start_listeners() -> any().
start_listeners() -> start_listeners() -> lists:foreach(fun start_listener/1, env(listeners)).
{ok, Listeners} = application:get_env(?APP, listeners),
lists:foreach(fun start_listener/1, Listeners).
%% Start mqtt listener %% Start mqtt listener
-spec start_listener(listener()) -> any(). -spec start_listener(listener()) -> any().
start_listener({mqtt, Port, Options}) -> start_listener({mqtt, Port, Opts}) -> start_listener(mqtt, Port, Opts);
start_listener(mqtt, Port, Options);
%% Start mqtt(SSL) listener %% Start mqtt(SSL) listener
start_listener({mqtts, Port, Options}) -> start_listener({mqtts, Port, Opts}) -> start_listener(mqtts, Port, Opts);
start_listener(mqtts, Port, Options);
%% Start http listener %% Start http listener
start_listener({http, Port, Options}) -> start_listener({http, Port, Opts}) ->
MFArgs = {emqttd_http, handle_request, []}, mochiweb:start_http(Port, Opts, {emqttd_http, handle_request, []});
mochiweb:start_http(Port, Options, MFArgs);
%% Start https listener %% Start https listener
start_listener({https, Port, Options}) -> start_listener({https, Port, Opts}) ->
MFArgs = {emqttd_http, handle_request, []}, mochiweb:start_http(Port, Opts, {emqttd_http, handle_request, []}).
mochiweb:start_http(Port, Options, MFArgs).
start_listener(Protocol, Port, Options) -> start_listener(Protocol, Port, Opts) ->
MFArgs = {emqttd_client, start_link, [env(mqtt)]}, MFArgs = {emqttd_client, start_link, [env(mqtt)]},
esockd:open(Protocol, Port, merge_sockopts(Options) , MFArgs). esockd:open(Protocol, Port, merge_sockopts(Opts), MFArgs).
merge_sockopts(Options) -> merge_sockopts(Options) ->
SockOpts = emqttd_opts:merge(?MQTT_SOCKOPTS, SockOpts = emqttd_opts:merge(?MQTT_SOCKOPTS,
proplists:get_value(sockopts, Options, [])), proplists:get_value(sockopts, Options, [])),
emqttd_opts:merge(Options, [{sockopts, SockOpts}]). emqttd_opts:merge(Options, [{sockopts, SockOpts}]).
%%------------------------------------------------------------------------------
%% @doc Stop Listeners %% @doc Stop Listeners
%% @end stop_listeners() -> lists:foreach(fun stop_listener/1, env(listeners)).
%%------------------------------------------------------------------------------
stop_listeners() ->
{ok, Listeners} = application:get_env(?APP, listeners),
lists:foreach(fun stop_listener/1, Listeners).
stop_listener({Protocol, Port, _Options}) -> stop_listener({Protocol, Port, _Opts}) -> esockd:close({Protocol, Port}).
esockd:close({Protocol, Port}).
%% @doc load all modules
load_all_mods() -> load_all_mods() ->
lists:foreach(fun load_mod/1, env(modules)). lists:foreach(fun load_mod/1, env(modules)).
load_mod({Name, Opts}) -> load_mod({Name, Opts}) ->
Mod = list_to_atom("emqttd_mod_" ++ atom_to_list(Name)), Mod = list_to_atom("emqttd_mod_" ++ atom_to_list(Name)),
case catch Mod:load(Opts) of case catch Mod:load(Opts) of
{ok, _State} -> lager:info("load module ~s successfully", [Name]); ok -> lager:info("Load module ~s successfully", [Name]);
{'EXIT', Reason} -> lager:error("load module ~s error: ~p", [Name, Reason]) {error, Error} -> lager:error("Load module ~s error: ~p", [Name, Error]);
{'EXIT', Reason} -> lager:error("Load module ~s error: ~p", [Name, Reason])
end. end.
is_mod_enabled(Name) -> %% @doc Is module enabled?
env(modules, Name) =/= undefined. -spec is_mod_enabled(Name :: atom()) -> boolean().
is_mod_enabled(Name) -> env(modules, Name) =/= undefined.
%% @doc Is running? %% @doc Is running?
-spec is_running(node()) -> boolean(). -spec is_running(node()) -> boolean().
@ -141,10 +111,7 @@ reg_name(M, Id) when is_atom(M), is_integer(Id) ->
seed_now() -> seed_now() ->
case erlang:function_exported(erlang, timestamp, 0) of case erlang:function_exported(erlang, timestamp, 0) of
true -> %% R18 true -> random:seed(erlang:timestamp()); %% R18
random:seed(erlang:timestamp()); false -> random:seed(os:timestamp()) %% compress 'now()' warning...
false ->
%% compress 'now()' warning...
random:seed(os:timestamp())
end. end.

View File

@ -1,30 +1,24 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Authentication and ACL Control.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Authentication and ACL Control Server
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_access_control). -module(emqttd_access_control).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
-behaviour(gen_server). -behaviour(gen_server).
@ -47,27 +41,22 @@
-define(ACCESS_CONTROL_TAB, mqtt_access_control). -define(ACCESS_CONTROL_TAB, mqtt_access_control).
%%%============================================================================= -type password() :: undefined | binary().
%%% API
%%%=============================================================================
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Start access control server %% API
%% @end %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Start access control server.
-spec start_link() -> {ok, pid()} | ignore | {error, any()}. -spec start_link() -> {ok, pid()} | ignore | {error, any()}.
start_link() -> start_link() -> start_link(emqttd:env(access)).
start_link(emqttd:env(access)).
-spec start_link(Opts :: list()) -> {ok, pid()} | ignore | {error, any()}. -spec start_link(Opts :: list()) -> {ok, pid()} | ignore | {error, any()}.
start_link(Opts) -> start_link(Opts) ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [Opts], []). gen_server:start_link({local, ?SERVER}, ?MODULE, [Opts], []).
%%------------------------------------------------------------------------------ %% @doc Authenticate MQTT Client.
%% @doc Authenticate MQTT Client -spec auth(Client :: mqtt_client(), Password :: password()) -> ok | {error, any()}.
%% @end
%%------------------------------------------------------------------------------
-spec auth(mqtt_client(), undefined | binary()) -> ok | {error, string()}.
auth(Client, Password) when is_record(Client, mqtt_client) -> auth(Client, Password) when is_record(Client, mqtt_client) ->
auth(Client, Password, lookup_mods(auth)). auth(Client, Password, lookup_mods(auth)).
auth(_Client, _Password, []) -> auth(_Client, _Password, []) ->
@ -80,41 +69,32 @@ auth(Client, Password, [{Mod, State, _Seq} | Mods]) ->
{'EXIT', Error} -> {error, Error} {'EXIT', Error} -> {error, Error}
end. end.
%%------------------------------------------------------------------------------
%% @doc Check ACL %% @doc Check ACL
%% @end
%%------------------------------------------------------------------------------
-spec check_acl(Client, PubSub, Topic) -> allow | deny when -spec check_acl(Client, PubSub, Topic) -> allow | deny when
Client :: mqtt_client(), Client :: mqtt_client(),
PubSub :: pubsub(), PubSub :: pubsub(),
Topic :: binary(). Topic :: binary().
check_acl(Client, PubSub, Topic) when ?IS_PUBSUB(PubSub) -> check_acl(Client, PubSub, Topic) when ?IS_PUBSUB(PubSub) ->
case lookup_mods(acl) of case lookup_mods(acl) of
[] -> allow; [] -> allow;
AclMods -> check_acl(Client, PubSub, Topic, AclMods) AclMods -> check_acl(Client, PubSub, Topic, AclMods)
end. end.
check_acl(#mqtt_client{client_id = ClientId}, PubSub, Topic, []) -> check_acl(#mqtt_client{client_id = ClientId}, PubSub, Topic, []) ->
lager:error("ACL: nomatch when ~s ~s ~s", [ClientId, PubSub, Topic]), lager:error("ACL: nomatch for ~s ~s ~s", [ClientId, PubSub, Topic]),
allow; allow;
check_acl(Client, PubSub, Topic, [{M, State, _Seq}|AclMods]) -> check_acl(Client, PubSub, Topic, [{Mod, State, _Seq}|AclMods]) ->
case M:check_acl({Client, PubSub, Topic}, State) of case Mod:check_acl({Client, PubSub, Topic}, State) of
allow -> allow; allow -> allow;
deny -> deny; deny -> deny;
ignore -> check_acl(Client, PubSub, Topic, AclMods) ignore -> check_acl(Client, PubSub, Topic, AclMods)
end. end.
%%------------------------------------------------------------------------------ %% @doc Reload ACL Rules.
%% @doc Reload ACL -spec reload_acl() -> list(ok | {error, any()}).
%% @end
%%------------------------------------------------------------------------------
-spec reload_acl() -> list() | {error, any()}.
reload_acl() -> reload_acl() ->
[M:reload_acl(State) || {M, State, _Seq} <- lookup_mods(acl)]. [Mod:reload_acl(State) || {Mod, State, _Seq} <- lookup_mods(acl)].
%%------------------------------------------------------------------------------ %% @doc Register Authentication or ACL module.
%% @doc Register authentication or ACL module
%% @end
%%------------------------------------------------------------------------------
-spec register_mod(auth | acl, atom(), list()) -> ok | {error, any()}. -spec register_mod(auth | acl, atom(), list()) -> ok | {error, any()}.
register_mod(Type, Mod, Opts) when Type =:= auth; Type =:= acl-> register_mod(Type, Mod, Opts) when Type =:= auth; Type =:= acl->
register_mod(Type, Mod, Opts, 0). register_mod(Type, Mod, Opts, 0).
@ -123,38 +103,28 @@ register_mod(Type, Mod, Opts) when Type =:= auth; Type =:= acl->
register_mod(Type, Mod, Opts, Seq) when Type =:= auth; Type =:= acl-> register_mod(Type, Mod, Opts, Seq) when Type =:= auth; Type =:= acl->
gen_server:call(?SERVER, {register_mod, Type, Mod, Opts, Seq}). gen_server:call(?SERVER, {register_mod, Type, Mod, Opts, Seq}).
%%------------------------------------------------------------------------------
%% @doc Unregister authentication or ACL module %% @doc Unregister authentication or ACL module
%% @end
%%------------------------------------------------------------------------------
-spec unregister_mod(Type :: auth | acl, Mod :: atom()) -> ok | {error, any()}. -spec unregister_mod(Type :: auth | acl, Mod :: atom()) -> ok | {error, any()}.
unregister_mod(Type, Mod) when Type =:= auth; Type =:= acl -> unregister_mod(Type, Mod) when Type =:= auth; Type =:= acl ->
gen_server:call(?SERVER, {unregister_mod, Type, Mod}). gen_server:call(?SERVER, {unregister_mod, Type, Mod}).
%%------------------------------------------------------------------------------ %% @doc Lookup authentication or ACL modules.
%% @doc Lookup authentication or ACL modules
%% @end
%%------------------------------------------------------------------------------
-spec lookup_mods(auth | acl) -> list(). -spec lookup_mods(auth | acl) -> list().
lookup_mods(Type) -> lookup_mods(Type) ->
case ets:lookup(?ACCESS_CONTROL_TAB, tab_key(Type)) of case ets:lookup(?ACCESS_CONTROL_TAB, tab_key(Type)) of
[] -> []; [] -> [];
[{_, Mods}] -> Mods [{_, Mods}] -> Mods
end. end.
tab_key(auth) -> auth_modules; tab_key(auth) -> auth_modules;
tab_key(acl) -> acl_modules. tab_key(acl) -> acl_modules.
%%------------------------------------------------------------------------------ %% @doc Stop access control server.
%% @doc Stop access control server stop() -> gen_server:call(?MODULE, stop).
%% @end
%%------------------------------------------------------------------------------
stop() ->
gen_server:call(?MODULE, stop).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([Opts]) -> init([Opts]) ->
ets:new(?ACCESS_CONTROL_TAB, [set, named_table, protected, {read_concurrency, true}]), ets:new(?ACCESS_CONTROL_TAB, [set, named_table, protected, {read_concurrency, true}]),
@ -164,48 +134,42 @@ init([Opts]) ->
{ok, state}. {ok, state}.
init_mods(auth, AuthMods) -> init_mods(auth, AuthMods) ->
[init_mod(fun authmod/1, Name, Opts) || {Name, Opts} <- AuthMods]; [init_mod(authmod(Name), Opts) || {Name, Opts} <- AuthMods];
init_mods(acl, AclMods) -> init_mods(acl, AclMods) ->
[init_mod(fun aclmod/1, Name, Opts) || {Name, Opts} <- AclMods]. [init_mod(aclmod(Name), Opts) || {Name, Opts} <- AclMods].
init_mod(Fun, Name, Opts) -> init_mod(Mod, Opts) ->
Module = Fun(Name), {ok, State} = Mod:init(Opts), {Mod, State, 0}.
{ok, State} = Module:init(Opts),
{Module, State, 0}.
handle_call({register_mod, Type, Mod, Opts, Seq}, _From, State) -> handle_call({register_mod, Type, Mod, Opts, Seq}, _From, State) ->
Mods = lookup_mods(Type), Mods = lookup_mods(Type),
Reply = Existed = lists:keyfind(Mod, 1, Mods),
case lists:keyfind(Mod, 1, Mods) of {reply, if_existed(Existed, fun() ->
false -> case catch Mod:init(Opts) of
case catch Mod:init(Opts) of {ok, ModState} ->
{ok, ModState} -> NewMods = lists:sort(fun({_, _, Seq1}, {_, _, Seq2}) ->
NewMods = Seq1 >= Seq2
lists:sort(fun({_, _, Seq1}, {_, _, Seq2}) -> end, [{Mod, ModState, Seq} | Mods]),
Seq1 >= Seq2 ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), NewMods});
end, [{Mod, ModState, Seq} | Mods]), {error, Error} ->
ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), NewMods}), lager:error("Access Control: register ~s error - ~p", [Mod, Error]),
ok; {error, Error};
{'EXIT', Error} -> {'EXIT', Reason} ->
lager:error("Access Control: register ~s error - ~p", [Mod, Error]), lager:error("Access Control: register ~s EXIT, reason - ~p", [Mod, Reason]),
{error, Error} {error, Reason}
end; end
_ -> end), State};
{error, existed}
end,
{reply, Reply, State};
handle_call({unregister_mod, Type, Mod}, _From, State) -> handle_call({unregister_mod, Type, Mod}, _From, State) ->
Mods = lookup_mods(Type), Mods = lookup_mods(Type),
Reply =
case lists:keyfind(Mod, 1, Mods) of case lists:keyfind(Mod, 1, Mods) of
false -> false ->
{error, not_found}; {reply, {error, not_found}, State};
_ -> _ ->
ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), lists:keydelete(Mod, 1, Mods)}), ok ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), lists:keydelete(Mod, 1, Mods)}),
end, {reply, ok, State}
{reply, Reply, State}; end;
handle_call(stop, _From, State) -> handle_call(stop, _From, State) ->
{stop, normal, ok, State}; {stop, normal, ok, State};
@ -226,9 +190,9 @@ terminate(_Reason, _State) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
authmod(Name) when is_atom(Name) -> authmod(Name) when is_atom(Name) ->
mod(emqttd_auth_, Name). mod(emqttd_auth_, Name).
@ -239,3 +203,6 @@ aclmod(Name) when is_atom(Name) ->
mod(Prefix, Name) -> mod(Prefix, Name) ->
list_to_atom(lists:concat([Prefix, Name])). list_to_atom(lists:concat([Prefix, Name])).
if_existed(false, Fun) -> Fun();
if_existed(true, _Fun) -> {error, existed}.

View File

@ -1,30 +1,24 @@
%%%----------------------------------------------------------------------------- %% -------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %% -------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Access Rule.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd ACL Rule
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_access_rule). -module(emqttd_access_rule).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
-type who() :: all | binary() | -type who() :: all | binary() |
@ -47,10 +41,7 @@
-define(ALLOW_DENY(A), ((A =:= allow) orelse (A =:= deny))). -define(ALLOW_DENY(A), ((A =:= allow) orelse (A =:= deny))).
%%------------------------------------------------------------------------------ %% @doc Compile Access Rule.
%% @doc Compile access rule
%% @end
%%------------------------------------------------------------------------------
compile({A, all}) when ?ALLOW_DENY(A) -> compile({A, all}) when ?ALLOW_DENY(A) ->
{A, all}; {A, all};
@ -96,10 +87,7 @@ bin(L) when is_list(L) ->
bin(B) when is_binary(B) -> bin(B) when is_binary(B) ->
B. B.
%%------------------------------------------------------------------------------ %% @doc Match Access Rule
%% @doc Match rule
%% @end
%%------------------------------------------------------------------------------
-spec match(mqtt_client(), topic(), rule()) -> {matched, allow} | {matched, deny} | nomatch. -spec match(mqtt_client(), topic(), rule()) -> {matched, allow} | {matched, deny} | nomatch.
match(_Client, _Topic, {AllowDeny, all}) when (AllowDeny =:= allow) orelse (AllowDeny =:= deny) -> match(_Client, _Topic, {AllowDeny, all}) when (AllowDeny =:= allow) orelse (AllowDeny =:= deny) ->
{matched, AllowDeny}; {matched, AllowDeny};

View File

@ -1,30 +1,24 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Internal ACL that load rules from etc/acl.config
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Internal ACL that load rules from etc/acl.config
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_acl_internal). -module(emqttd_acl_internal).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
-export([all_rules/0]). -export([all_rules/0]).
@ -38,14 +32,11 @@
-record(state, {acl_file, nomatch = allow}). -record(state, {acl_file, nomatch = allow}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Read all rules %% @doc Read all rules
%% @end
%%------------------------------------------------------------------------------
-spec all_rules() -> list(emqttd_access_rule:rule()). -spec all_rules() -> list(emqttd_access_rule:rule()).
all_rules() -> all_rules() ->
case ets:lookup(?ACL_RULE_TAB, all_rules) of case ets:lookup(?ACL_RULE_TAB, all_rules) of
@ -53,22 +44,21 @@ all_rules() ->
[{_, Rules}] -> Rules [{_, Rules}] -> Rules
end. end.
%%%============================================================================= %%--------------------------------------------------------------------
%%% ACL callbacks %% ACL callbacks
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Init internal ACL %% @doc Init internal ACL
%% @end
%%------------------------------------------------------------------------------
-spec init(AclOpts :: list()) -> {ok, State :: any()}. -spec init(AclOpts :: list()) -> {ok, State :: any()}.
init(AclOpts) -> init(AclOpts) ->
ets:new(?ACL_RULE_TAB, [set, public, named_table, {read_concurrency, true}]), ets:new(?ACL_RULE_TAB, [set, public, named_table, {read_concurrency, true}]),
AclFile = proplists:get_value(file, AclOpts), AclFile = proplists:get_value(file, AclOpts),
Default = proplists:get_value(nomatch, AclOpts, allow), Default = proplists:get_value(nomatch, AclOpts, allow),
State = #state{acl_file = AclFile, nomatch = Default}, State = #state{acl_file = AclFile, nomatch = Default},
load_rules_from_file(State), case load_rules_from_file(State) of
{ok, State}. ok -> {ok, State};
{error, Error} -> {error, Error}
end.
load_rules_from_file(#state{acl_file = AclFile}) -> load_rules_from_file(#state{acl_file = AclFile}) ->
{ok, Terms} = file:consult(AclFile), {ok, Terms} = file:consult(AclFile),
@ -92,10 +82,7 @@ filter(subscribe, {_AllowDeny, _Who, subscribe, _Topics}) ->
filter(_PubSub, {_AllowDeny, _Who, _, _Topics}) -> filter(_PubSub, {_AllowDeny, _Who, _, _Topics}) ->
false. false.
%%------------------------------------------------------------------------------
%% @doc Check ACL %% @doc Check ACL
%% @end
%%------------------------------------------------------------------------------
-spec check_acl({Client, PubSub, Topic}, State) -> allow | deny | ignore when -spec check_acl({Client, PubSub, Topic}, State) -> allow | deny | ignore when
Client :: mqtt_client(), Client :: mqtt_client(),
PubSub :: pubsub(), PubSub :: pubsub(),
@ -123,10 +110,7 @@ match(Client, Topic, [Rule|Rules]) ->
{matched, AllowDeny} -> {matched, AllowDeny} {matched, AllowDeny} -> {matched, AllowDeny}
end. end.
%%------------------------------------------------------------------------------
%% @doc Reload ACL %% @doc Reload ACL
%% @end
%%------------------------------------------------------------------------------
-spec reload_acl(State :: #state{}) -> ok | {error, Reason :: any()}. -spec reload_acl(State :: #state{}) -> ok | {error, Reason :: any()}.
reload_acl(State) -> reload_acl(State) ->
case catch load_rules_from_file(State) of case catch load_rules_from_file(State) of
@ -134,10 +118,7 @@ reload_acl(State) ->
_ -> ok _ -> ok
end. end.
%%------------------------------------------------------------------------------
%% @doc ACL Module Description %% @doc ACL Module Description
%% @end
%%------------------------------------------------------------------------------
-spec description() -> string(). -spec description() -> string().
description() -> "Internal ACL with etc/acl.config". description() -> "Internal ACL with etc/acl.config".

View File

@ -1,35 +1,29 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc ACL module behaviour.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc ACL module behaviour
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_acl_mod). -module(emqttd_acl_mod).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
%%%============================================================================= %%--------------------------------------------------------------------
%%% ACL behavihour %% ACL behavihour
%%%============================================================================= %%--------------------------------------------------------------------
-ifdef(use_specs). -ifdef(use_specs).
@ -49,9 +43,9 @@
-export([behaviour_info/1]). -export([behaviour_info/1]).
behaviour_info(callbacks) -> behaviour_info(callbacks) ->
[{init, 1}, {check_acl, 2}, {reload_acl, 1}, {description, 0}]; [{init, 1}, {check_acl, 2}, {reload_acl, 1}, {description, 0}];
behaviour_info(_Other) -> behaviour_info(_Other) ->
undefined. undefined.
-endif. -endif.

View File

@ -1,30 +1,24 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Copy alarm_handler
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Copy alarm_handler
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_alarm). -module(emqttd_alarm).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
-behaviour(gen_event). -behaviour(gen_event).
@ -41,9 +35,9 @@
-export([init/1, handle_event/2, handle_call/2, handle_info/2, -export([init/1, handle_event/2, handle_call/2, handle_info/2,
terminate/2, code_change/3]). terminate/2, code_change/3]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
start_link() -> start_link() ->
start_with(fun(Pid) -> gen_event:add_handler(Pid, ?MODULE, []) end). start_with(fun(Pid) -> gen_event:add_handler(Pid, ?MODULE, []) end).
@ -54,8 +48,7 @@ start_with(Fun) ->
Error -> Error Error -> Error
end. end.
alarm_fun() -> alarm_fun() -> alarm_fun(false).
alarm_fun(false).
alarm_fun(Bool) -> alarm_fun(Bool) ->
fun(alert, _Alarm) when Bool =:= true -> alarm_fun(true); fun(alert, _Alarm) when Bool =:= true -> alarm_fun(true);
@ -85,12 +78,11 @@ add_alarm_handler(Module, Args) when is_atom(Module) ->
delete_alarm_handler(Module) when is_atom(Module) -> delete_alarm_handler(Module) when is_atom(Module) ->
gen_event:delete_handler(?ALARM_MGR, Module, []). gen_event:delete_handler(?ALARM_MGR, Module, []).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Default Alarm handler %% Default Alarm handler
%%%============================================================================= %%--------------------------------------------------------------------
init(_) -> init(_) -> {ok, []}.
{ok, []}.
handle_event({set_alarm, Alarm = #mqtt_alarm{id = AlarmId, handle_event({set_alarm, Alarm = #mqtt_alarm{id = AlarmId,
severity = Severity, severity = Severity,
@ -131,9 +123,9 @@ terminate(_, _) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
alarm_msg(Type, AlarmId, Json) -> alarm_msg(Type, AlarmId, Json) ->
Msg = emqttd_message:make(alarm, Msg = emqttd_message:make(alarm,

View File

@ -1,30 +1,24 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd application.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd application.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_app). -module(emqttd_app).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd_cli.hrl"). -include("emqttd_cli.hrl").
-behaviour(application). -behaviour(application).
@ -32,9 +26,9 @@
%% Application callbacks %% Application callbacks
-export([start/2, stop/1]). -export([start/2, stop/1]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Application callbacks %% Application callbacks
%%%============================================================================= %%--------------------------------------------------------------------
-spec start(StartType, StartArgs) -> {ok, pid()} | {ok, pid(), State} | {error, Reason} when -spec start(StartType, StartArgs) -> {ok, pid()} | {ok, pid(), State} | {error, Reason} when
StartType :: normal | {takeover, node()} | {failover, node()}, StartType :: normal | {takeover, node()} | {failover, node()},

View File

@ -1,30 +1,24 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Anonymous Authentication Module
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Anonymous Authentication Module
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_auth_anonymous). -module(emqttd_auth_anonymous).
-author("Feng Lee <feng@emqtt.io>").
-behaviour(emqttd_auth_mod). -behaviour(emqttd_auth_mod).
-export([init/1, check/3, description/0]). -export([init/1, check/3, description/0]).

View File

@ -1,34 +1,27 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc ClientId Authentication Module.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc ClientId Authentication Module
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_auth_clientid). -module(emqttd_auth_clientid).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
-export([add_clientid/1, add_clientid/2, -export([add_clientid/1, add_clientid/2, lookup_clientid/1, remove_clientid/1,
lookup_clientid/1, remove_clientid/1,
all_clientids/0]). all_clientids/0]).
-behaviour(emqttd_auth_mod). -behaviour(emqttd_auth_mod).
@ -40,87 +33,71 @@
-record(?AUTH_CLIENTID_TAB, {client_id, ipaddr, password}). -record(?AUTH_CLIENTID_TAB, {client_id, ipaddr, password}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Add clientid %% @doc Add clientid
%% @end
%%------------------------------------------------------------------------------
-spec add_clientid(binary()) -> {atomic, ok} | {aborted, any()}. -spec add_clientid(binary()) -> {atomic, ok} | {aborted, any()}.
add_clientid(ClientId) when is_binary(ClientId) -> add_clientid(ClientId) when is_binary(ClientId) ->
R = #mqtt_auth_clientid{client_id = ClientId}, R = #mqtt_auth_clientid{client_id = ClientId},
mnesia:transaction(fun mnesia:write/1, [R]). mnesia:transaction(fun mnesia:write/1, [R]).
%%------------------------------------------------------------------------------
%% @doc Add clientid with password %% @doc Add clientid with password
%% @end
%%------------------------------------------------------------------------------
-spec add_clientid(binary(), binary()) -> {atomic, ok} | {aborted, any()}. -spec add_clientid(binary(), binary()) -> {atomic, ok} | {aborted, any()}.
add_clientid(ClientId, Password) -> add_clientid(ClientId, Password) ->
R = #mqtt_auth_clientid{client_id = ClientId, password = Password}, R = #mqtt_auth_clientid{client_id = ClientId, password = Password},
mnesia:transaction(fun mnesia:write/1, [R]). mnesia:transaction(fun mnesia:write/1, [R]).
%%------------------------------------------------------------------------------
%% @doc Lookup clientid %% @doc Lookup clientid
%% @end -spec lookup_clientid(binary()) -> list(#mqtt_auth_clientid{}).
%%------------------------------------------------------------------------------
-spec lookup_clientid(binary()) -> list().
lookup_clientid(ClientId) -> lookup_clientid(ClientId) ->
mnesia:dirty_read(?AUTH_CLIENTID_TAB, ClientId). mnesia:dirty_read(?AUTH_CLIENTID_TAB, ClientId).
%%------------------------------------------------------------------------------
%% @doc Lookup all clientids %% @doc Lookup all clientids
%% @end
%%------------------------------------------------------------------------------
-spec all_clientids() -> list(binary()). -spec all_clientids() -> list(binary()).
all_clientids() -> all_clientids() -> mnesia:dirty_all_keys(?AUTH_CLIENTID_TAB).
mnesia:dirty_all_keys(?AUTH_CLIENTID_TAB).
%%------------------------------------------------------------------------------
%% @doc Remove clientid %% @doc Remove clientid
%% @end
%%------------------------------------------------------------------------------
-spec remove_clientid(binary()) -> {atomic, ok} | {aborted, any()}. -spec remove_clientid(binary()) -> {atomic, ok} | {aborted, any()}.
remove_clientid(ClientId) -> remove_clientid(ClientId) ->
mnesia:transaction(fun mnesia:delete/1, [{?AUTH_CLIENTID_TAB, ClientId}]). mnesia:transaction(fun mnesia:delete/1, [{?AUTH_CLIENTID_TAB, ClientId}]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% emqttd_auth_mod callbacks %% emqttd_auth_mod callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init(Opts) -> init(Opts) ->
mnesia:create_table(?AUTH_CLIENTID_TAB, [ mnesia:create_table(?AUTH_CLIENTID_TAB, [
{ram_copies, [node()]}, {ram_copies, [node()]},
{attributes, record_info(fields, ?AUTH_CLIENTID_TAB)}]), {attributes, record_info(fields, ?AUTH_CLIENTID_TAB)}]),
mnesia:add_table_copy(?AUTH_CLIENTID_TAB, node(), ram_copies), mnesia:add_table_copy(?AUTH_CLIENTID_TAB, node(), ram_copies),
case proplists:get_value(file, Opts) of load(proplists:get_value(file, Opts)),
undefined -> ok;
File -> load(File)
end,
{ok, Opts}. {ok, Opts}.
check(#mqtt_client{client_id = undefined}, _Password, []) -> check(#mqtt_client{client_id = undefined}, _Password, _Opts) ->
{error, "ClientId undefined"}; {error, clientid_undefined};
check(#mqtt_client{client_id = ClientId, peername = {IpAddress, _}}, _Password, []) -> check(#mqtt_client{client_id = ClientId, peername = {IpAddress, _}}, _Password, []) ->
check_clientid_only(ClientId, IpAddress); check_clientid_only(ClientId, IpAddress);
check(#mqtt_client{client_id = ClientId, peername = {IpAddress, _}}, _Password, [{password, no}|_]) -> check(#mqtt_client{client_id = ClientId, peername = {IpAddress, _}}, _Password, [{password, no}|_]) ->
check_clientid_only(ClientId, IpAddress); check_clientid_only(ClientId, IpAddress);
check(_Client, undefined, [{password, yes}|_]) -> check(_Client, undefined, [{password, yes}|_]) ->
{error, "Password undefined"}; {error, password_undefined};
check(#mqtt_client{client_id = ClientId}, Password, [{password, yes}|_]) -> check(#mqtt_client{client_id = ClientId}, Password, [{password, yes}|_]) ->
case mnesia:dirty_read(?AUTH_CLIENTID_TAB, ClientId) of case mnesia:dirty_read(?AUTH_CLIENTID_TAB, ClientId) of
[] -> {error, "ClientId Not Found"}; [] -> {error, clientid_not_found};
[#?AUTH_CLIENTID_TAB{password = Password}] -> ok; %% TODO: plaintext?? [#?AUTH_CLIENTID_TAB{password = Password}] -> ok; %% TODO: plaintext??
_ -> {error, "Password Not Right"} _ -> {error, password_error}
end. end.
description() -> "ClientId authentication module". description() -> "ClientId authentication module".
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
load(undefined) ->
ok;
load(File) -> load(File) ->
{ok, Fd} = file:open(File, [read]), {ok, Fd} = file:open(File, [read]),
@ -149,13 +126,13 @@ load(Fd, eof, Clients) ->
check_clientid_only(ClientId, IpAddr) -> check_clientid_only(ClientId, IpAddr) ->
case mnesia:dirty_read(?AUTH_CLIENTID_TAB, ClientId) of case mnesia:dirty_read(?AUTH_CLIENTID_TAB, ClientId) of
[] -> {error, "ClientId Not Found"}; [] -> {error, clientid_not_found};
[#?AUTH_CLIENTID_TAB{ipaddr = undefined}] -> ok; [#?AUTH_CLIENTID_TAB{ipaddr = undefined}] -> ok;
[#?AUTH_CLIENTID_TAB{ipaddr = {_, {Start, End}}}] -> [#?AUTH_CLIENTID_TAB{ipaddr = {_, {Start, End}}}] ->
I = esockd_access:atoi(IpAddr), I = esockd_access:atoi(IpAddr),
case I >= Start andalso I =< End of case I >= Start andalso I =< End of
true -> ok; true -> ok;
false -> {error, "ClientId with wrong IP address"} false -> {error, wrong_ipaddr}
end end
end. end.

View File

@ -1,30 +1,24 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc LDAP Authentication Module
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc LDAP Authentication Module
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_auth_ldap). -module(emqttd_auth_ldap).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
-import(proplists, [get_value/2, get_value/3]). -import(proplists, [get_value/2, get_value/3]).
@ -51,11 +45,11 @@ init(Opts) ->
{ok, #state{servers = Servers, user_dn = UserDn, options = LdapOpts}}. {ok, #state{servers = Servers, user_dn = UserDn, options = LdapOpts}}.
check(#mqtt_client{username = undefined}, _Password, _State) -> check(#mqtt_client{username = undefined}, _Password, _State) ->
{error, "Username undefined"}; {error, username_undefined};
check(_Client, undefined, _State) -> check(_Client, undefined, _State) ->
{error, "Password undefined"}; {error, password_undefined};
check(_Client, <<>>, _State) -> check(_Client, <<>>, _State) ->
{error, "Password undefined"}; {error, password_undefined};
check(#mqtt_client{username = Username}, Password, check(#mqtt_client{username = Username}, Password,
#state{servers = Servers, user_dn = UserDn, options = Options}) -> #state{servers = Servers, user_dn = UserDn, options = Options}) ->
case eldap:open(Servers, Options) of case eldap:open(Servers, Options) of
@ -71,7 +65,7 @@ ldap_bind(LDAP, UserDn, Password) ->
ok -> ok ->
ok; ok;
{error, invalidCredentials} -> {error, invalidCredentials} ->
{error, "LDAP Invalid Credentials"}; {error, invalid_credentials};
{error, Error} -> {error, Error} ->
{error, Error}; {error, Error};
{'EXIT', Reason} -> {'EXIT', Reason} ->

View File

@ -1,39 +1,33 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Authentication Behaviour.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd Authentication Behaviour
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_auth_mod). -module(emqttd_auth_mod).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
-export([passwd_hash/2]). -export([passwd_hash/2]).
-type hash_type() :: plain | md5 | sha | sha256. -type hash_type() :: plain | md5 | sha | sha256.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Auth behavihour %% Authentication behavihour
%%%============================================================================= %%--------------------------------------------------------------------
-ifdef(use_specs). -ifdef(use_specs).

View File

@ -1,30 +1,24 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Authentication with username and password
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Authentication with username and password
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_auth_username). -module(emqttd_auth_username).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
-include("emqttd_cli.hrl"). -include("emqttd_cli.hrl").
@ -44,63 +38,54 @@
-record(?AUTH_USERNAME_TAB, {username, password}). -record(?AUTH_USERNAME_TAB, {username, password}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% CLI %% CLI
%%%============================================================================= %%--------------------------------------------------------------------
cli(["add", Username, Password]) -> cli(["add", Username, Password]) ->
?PRINT("~p~n", [add_user(list_to_binary(Username), list_to_binary(Password))]); ?PRINT("~p~n", [add_user(iolist_to_binary(Username), iolist_to_binary(Password))]);
cli(["del", Username]) -> cli(["del", Username]) ->
?PRINT("~p~n", [remove_user(list_to_binary(Username))]); ?PRINT("~p~n", [remove_user(iolist_to_binary(Username))]);
cli(_) -> cli(_) ->
?USAGE([{"users add <Username> <Password>", "add user"}, ?USAGE([{"users add <Username> <Password>", "Add User"},
{"users del <Username>", "delete user"}]). {"users del <Username>", "Delete User"}]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------ %% @doc Add User
%% @doc Add user -spec add_user(binary(), binary()) -> ok | {error, any()}.
%% @end
%%------------------------------------------------------------------------------
-spec add_user(binary(), binary()) -> {atomic, ok} | {aborted, any()}.
add_user(Username, Password) -> add_user(Username, Password) ->
User = #?AUTH_USERNAME_TAB{username = Username, password = hash(Password)}, User = #?AUTH_USERNAME_TAB{username = Username, password = hash(Password)},
mnesia:transaction(fun mnesia:write/1, [User]). ret(mnesia:transaction(fun mnesia:write/1, [User])).
add_default_user(Username, Password) -> add_default_user(Username, Password) ->
add_user(bin(Username), bin(Password)). add_user(iolist_to_binary(Username), iolist_to_binary(Password)).
%%------------------------------------------------------------------------------
%% @doc Lookup user by username %% @doc Lookup user by username
%% @end
%%------------------------------------------------------------------------------
-spec lookup_user(binary()) -> list(). -spec lookup_user(binary()) -> list().
lookup_user(Username) -> lookup_user(Username) ->
mnesia:dirty_read(?AUTH_USERNAME_TAB, Username). mnesia:dirty_read(?AUTH_USERNAME_TAB, Username).
%%------------------------------------------------------------------------------
%% @doc Remove user %% @doc Remove user
%% @end -spec remove_user(binary()) -> ok | {error, any()}.
%%------------------------------------------------------------------------------
-spec remove_user(binary()) -> {atomic, ok} | {aborted, any()}.
remove_user(Username) -> remove_user(Username) ->
mnesia:transaction(fun mnesia:delete/1, [{?AUTH_USERNAME_TAB, Username}]). ret(mnesia:transaction(fun mnesia:delete/1, [{?AUTH_USERNAME_TAB, Username}])).
ret({atomic, ok}) -> ok;
ret({aborted, Error}) -> {error, Error}.
%%------------------------------------------------------------------------------
%% @doc All usernames %% @doc All usernames
%% @end
%%------------------------------------------------------------------------------
-spec all_users() -> list(). -spec all_users() -> list().
all_users() -> all_users() -> mnesia:dirty_all_keys(?AUTH_USERNAME_TAB).
mnesia:dirty_all_keys(?AUTH_USERNAME_TAB).
%%--------------------------------------------------------------------
%% emqttd_auth_mod callbacks
%%--------------------------------------------------------------------
%%%=============================================================================
%%% emqttd_auth callbacks
%%%=============================================================================
init(DefautUsers) -> init(DefautUsers) ->
mnesia:create_table(?AUTH_USERNAME_TAB, [ mnesia:create_table(?AUTH_USERNAME_TAB, [
{disc_copies, [node()]}, {disc_copies, [node()]},
@ -113,40 +98,33 @@ init(DefautUsers) ->
{ok, []}. {ok, []}.
check(#mqtt_client{username = undefined}, _Password, _Opts) -> check(#mqtt_client{username = undefined}, _Password, _Opts) ->
{error, "Username undefined"}; {error, username_undefined};
check(_User, undefined, _Opts) -> check(_User, undefined, _Opts) ->
{error, "Password undefined"}; {error, password_undefined};
check(#mqtt_client{username = Username}, Password, _Opts) -> check(#mqtt_client{username = Username}, Password, _Opts) ->
case mnesia:dirty_read(?AUTH_USERNAME_TAB, Username) of case mnesia:dirty_read(?AUTH_USERNAME_TAB, Username) of
[] -> [] ->
{error, "Username Not Found"}; {error, username_not_found};
[#?AUTH_USERNAME_TAB{password = <<Salt:4/binary, Hash/binary>>}] -> [#?AUTH_USERNAME_TAB{password = <<Salt:4/binary, Hash/binary>>}] ->
case Hash =:= md5_hash(Salt, Password) of case Hash =:= md5_hash(Salt, Password) of
true -> ok; true -> ok;
false -> {error, "Password Not Right"} false -> {error, password_error}
end end
end. end.
description() -> description() ->
"Username password authentication module". "Username password authentication module".
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
hash(Password) -> hash(Password) ->
SaltBin = salt(), SaltBin = salt(), <<SaltBin/binary, (md5_hash(SaltBin, Password))/binary>>.
<<SaltBin/binary, (md5_hash(SaltBin, Password))/binary>>.
md5_hash(SaltBin, Password) -> md5_hash(SaltBin, Password) ->
erlang:md5(<<SaltBin/binary, Password/binary>>). erlang:md5(<<SaltBin/binary, Password/binary>>).
salt() -> salt() ->
emqttd:seed_now(), emqttd:seed_now(), Salt = random:uniform(16#ffffffff), <<Salt:32>>.
Salt = random:uniform(16#ffffffff),
<<Salt:32>>.
bin(A) when is_atom(A) -> bin(atom_to_list(A));
bin(L) when is_list(L) -> list_to_binary(L);
bin(B) when is_binary(B) -> B.

View File

@ -1,30 +1,25 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd bridge
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd bridge
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_bridge). -module(emqttd_bridge).
-behaviour(gen_server2).
-include("emqttd.hrl"). -include("emqttd.hrl").
-include("emqttd_protocol.hrl"). -include("emqttd_protocol.hrl").
@ -34,8 +29,6 @@
%% API Function Exports %% API Function Exports
-export([start_link/3]). -export([start_link/3]).
-behaviour(gen_server).
%% gen_server Function Exports %% gen_server Function Exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]). terminate/2, code_change/3]).
@ -59,32 +52,29 @@
-export_type([option/0]). -export_type([option/0]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Start a bridge %% @doc Start a bridge
%% @end
%%------------------------------------------------------------------------------
-spec start_link(atom(), binary(), [option()]) -> {ok, pid()} | ignore | {error, term()}. -spec start_link(atom(), binary(), [option()]) -> {ok, pid()} | ignore | {error, term()}.
start_link(Node, SubTopic, Options) -> start_link(Node, Topic, Options) ->
gen_server:start_link(?MODULE, [Node, SubTopic, Options], []). gen_server2:start_link(?MODULE, [Node, Topic, Options], []).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([Node, SubTopic, Options]) -> init([Node, Topic, Options]) ->
process_flag(trap_exit, true), process_flag(trap_exit, true),
case net_kernel:connect_node(Node) of case net_kernel:connect_node(Node) of
true -> true ->
true = erlang:monitor_node(Node, true), true = erlang:monitor_node(Node, true),
State = parse_opts(Options, #state{node = Node, subtopic = SubTopic}), State = parse_opts(Options, #state{node = Node, subtopic = Topic}),
MQueue = emqttd_mqueue:new(qname(Node, SubTopic), MQueue = emqttd_mqueue:new(qname(Node, Topic),
[{max_len, State#state.max_queue_len}], [{max_len, State#state.max_queue_len}],
emqttd_alarm:alarm_fun()), emqttd_alarm:alarm_fun()),
emqttd_pubsub:subscribe({SubTopic, State#state.qos}), emqttd_pubsub:subscribe({Topic, State#state.qos}),
{ok, State#state{mqueue = MQueue}}; {ok, State#state{mqueue = MQueue}};
false -> false ->
{stop, {cannot_connect, Node}} {stop, {cannot_connect, Node}}
@ -105,10 +95,10 @@ parse_opts([{ping_down_interval, Interval} | Opts], State) ->
parse_opts([_Opt | Opts], State) -> parse_opts([_Opt | Opts], State) ->
parse_opts(Opts, State). parse_opts(Opts, State).
qname(Node, SubTopic) when is_atom(Node) -> qname(Node, Topic) when is_atom(Node) ->
qname(atom_to_list(Node), SubTopic); qname(atom_to_list(Node), Topic);
qname(Node, SubTopic) -> qname(Node, Topic) ->
list_to_binary(["Bridge:", Node, ":", SubTopic]). iolist_to_binary(["Bridge:", Node, ":", Topic]).
handle_call(Req, _From, State) -> handle_call(Req, _From, State) ->
?UNEXPECTED_REQ(Req, State). ?UNEXPECTED_REQ(Req, State).
@ -163,9 +153,9 @@ terminate(_Reason, _State) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
dequeue(State = #state{mqueue = MQ}) -> dequeue(State = #state{mqueue = MQ}) ->
case emqttd_mqueue:out(MQ) of case emqttd_mqueue:out(MQ) of

View File

@ -1,103 +1,75 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Bridge Supervisor
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Bridge Supervisor
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_bridge_sup). -module(emqttd_bridge_sup).
-behavior(supervisor). -behavior(supervisor).
-export([start_link/0, -export([start_link/0, bridges/0, start_bridge/2, start_bridge/3, stop_bridge/2]).
bridges/0,
start_bridge/2, start_bridge/3,
stop_bridge/2]).
-export([init/1]). -export([init/1]).
%%%============================================================================= -define(BRIDGE_ID(Node, Topic), {bridge, Node, Topic}).
%%% API
%%%============================================================================= %%--------------------------------------------------------------------
%% API
%%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Start bridge supervisor %% @doc Start bridge supervisor
%% @end
%%------------------------------------------------------------------------------
start_link() -> start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []). supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%%------------------------------------------------------------------------------
%% @doc List all bridges %% @doc List all bridges
%% @end
%%------------------------------------------------------------------------------
-spec bridges() -> [{tuple(), pid()}]. -spec bridges() -> [{tuple(), pid()}].
bridges() -> bridges() ->
[{{Node, SubTopic}, Pid} || {{bridge, Node, SubTopic}, Pid, worker, _} [{{Node, Topic}, Pid} || {?BRIDGE_ID(Node, Topic), Pid, worker, _}
<- supervisor:which_children(?MODULE)]. <- supervisor:which_children(?MODULE)].
%%------------------------------------------------------------------------------
%% @doc Start a bridge %% @doc Start a bridge
%% @end
%%------------------------------------------------------------------------------
-spec start_bridge(atom(), binary()) -> {ok, pid()} | {error, any()}. -spec start_bridge(atom(), binary()) -> {ok, pid()} | {error, any()}.
start_bridge(Node, SubTopic) when is_atom(Node) and is_binary(SubTopic) -> start_bridge(Node, Topic) when is_atom(Node) andalso is_binary(Topic) ->
start_bridge(Node, SubTopic, []). start_bridge(Node, Topic, []).
-spec start_bridge(atom(), binary(), [emqttd_bridge:option()]) -> {ok, pid()} | {error, any()}. -spec start_bridge(atom(), binary(), [emqttd_bridge:option()]) -> {ok, pid()} | {error, any()}.
start_bridge(Node, SubTopic, Options) when is_atom(Node) and is_binary(SubTopic) -> start_bridge(Node, _Topic, _Options) when Node =:= node() ->
case Node =:= node() of {error, bridge_to_self};
true -> start_bridge(Node, Topic, Options) when is_atom(Node) andalso is_binary(Topic) ->
{error, bridge_to_self}; Options1 = emqttd_opts:merge(emqttd_broker:env(bridge), Options),
false -> supervisor:start_child(?MODULE, bridge_spec(Node, Topic, Options1)).
Options1 = emqttd_opts:merge(emqttd_broker:env(bridge), Options),
supervisor:start_child(?MODULE, bridge_spec(Node, SubTopic, Options1))
end.
%%------------------------------------------------------------------------------
%% @doc Stop a bridge %% @doc Stop a bridge
%% @end
%%------------------------------------------------------------------------------
-spec stop_bridge(atom(), binary()) -> {ok, pid()} | ok. -spec stop_bridge(atom(), binary()) -> {ok, pid()} | ok.
stop_bridge(Node, SubTopic) -> stop_bridge(Node, Topic) when is_atom(Node) andalso is_binary(Topic) ->
ChildId = bridge_id(Node, SubTopic), ChildId = ?BRIDGE_ID(Node, Topic),
case supervisor:terminate_child(?MODULE, ChildId) of case supervisor:terminate_child(?MODULE, ChildId) of
ok -> ok -> supervisor:delete_child(?MODULE, ChildId);
supervisor:delete_child(?MODULE, ChildId); {error, Reason} -> {error, Reason}
{error, Reason} ->
{error, Reason}
end. end.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Supervisor callbacks %% Supervisor callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([]) -> init([]) ->
{ok, {{one_for_one, 10, 100}, []}}. {ok, {{one_for_one, 10, 100}, []}}.
bridge_id(Node, SubTopic) -> bridge_spec(Node, Topic, Options) ->
{bridge, Node, SubTopic}. ChildId = ?BRIDGE_ID(Node, Topic),
{ChildId, {emqttd_bridge, start_link, [Node, Topic, Options]},
bridge_spec(Node, SubTopic, Options) ->
ChildId = bridge_id(Node, SubTopic),
{ChildId, {emqttd_bridge, start_link, [Node, SubTopic, Options]},
transient, 10000, worker, [emqttd_bridge]}. transient, 10000, worker, [emqttd_bridge]}.

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd broker
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd broker
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_broker). -module(emqttd_broker).
-behaviour(gen_server). -behaviour(gen_server).
@ -67,78 +60,51 @@
sysdescr % Broker description sysdescr % Broker description
]). ]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Start emqttd broker %% @doc Start emqttd broker
%% @end
%%------------------------------------------------------------------------------
-spec start_link() -> {ok, pid()} | ignore | {error, any()}. -spec start_link() -> {ok, pid()} | ignore | {error, any()}.
start_link() -> start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
%%------------------------------------------------------------------------------
%% @doc Get running nodes %% @doc Get running nodes
%% @end
%%------------------------------------------------------------------------------
-spec running_nodes() -> list(node()). -spec running_nodes() -> list(node()).
running_nodes() -> running_nodes() ->
mnesia:system_info(running_db_nodes). mnesia:system_info(running_db_nodes).
%%------------------------------------------------------------------------------
%% @doc Subscribe broker event %% @doc Subscribe broker event
%% @end
%%------------------------------------------------------------------------------
-spec subscribe(EventType :: any()) -> ok. -spec subscribe(EventType :: any()) -> ok.
subscribe(EventType) -> subscribe(EventType) ->
gproc:reg({p, l, {broker, EventType}}). gproc:reg({p, l, {broker, EventType}}).
%%------------------------------------------------------------------------------
%% @doc Notify broker event %% @doc Notify broker event
%% @end
%%------------------------------------------------------------------------------
-spec notify(EventType :: any(), Event :: any()) -> ok. -spec notify(EventType :: any(), Event :: any()) -> ok.
notify(EventType, Event) -> notify(EventType, Event) ->
Key = {broker, EventType}, Key = {broker, EventType},
gproc:send({p, l, Key}, {self(), Key, Event}). gproc:send({p, l, Key}, {self(), Key, Event}).
%%------------------------------------------------------------------------------
%% @doc Get broker env %% @doc Get broker env
%% @end
%%------------------------------------------------------------------------------
env(Name) -> env(Name) ->
proplists:get_value(Name, emqttd:env(broker)). proplists:get_value(Name, emqttd:env(broker)).
%%------------------------------------------------------------------------------
%% @doc Get broker version %% @doc Get broker version
%% @end
%%------------------------------------------------------------------------------
-spec version() -> string(). -spec version() -> string().
version() -> version() ->
{ok, Version} = application:get_key(emqttd, vsn), Version. {ok, Version} = application:get_key(emqttd, vsn), Version.
%%------------------------------------------------------------------------------
%% @doc Get broker description %% @doc Get broker description
%% @end
%%------------------------------------------------------------------------------
-spec sysdescr() -> string(). -spec sysdescr() -> string().
sysdescr() -> sysdescr() ->
{ok, Descr} = application:get_key(emqttd, description), Descr. {ok, Descr} = application:get_key(emqttd, description), Descr.
%%------------------------------------------------------------------------------
%% @doc Get broker uptime %% @doc Get broker uptime
%% @end
%%------------------------------------------------------------------------------
-spec uptime() -> string(). -spec uptime() -> string().
uptime() -> uptime() ->
gen_server:call(?SERVER, uptime). gen_server:call(?SERVER, uptime).
%%------------------------------------------------------------------------------
%% @doc Get broker datetime %% @doc Get broker datetime
%% @end
%%------------------------------------------------------------------------------
-spec datetime() -> string(). -spec datetime() -> string().
datetime() -> datetime() ->
{{Y, M, D}, {H, MM, S}} = calendar:local_time(), {{Y, M, D}, {H, MM, S}} = calendar:local_time(),
@ -146,26 +112,17 @@ datetime() ->
io_lib:format( io_lib:format(
"~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w", [Y, M, D, H, MM, S])). "~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w", [Y, M, D, H, MM, S])).
%%------------------------------------------------------------------------------
%% @doc Hook %% @doc Hook
%% @end
%%------------------------------------------------------------------------------
-spec hook(Hook :: atom(), Name :: any(), MFA :: mfa()) -> ok | {error, any()}. -spec hook(Hook :: atom(), Name :: any(), MFA :: mfa()) -> ok | {error, any()}.
hook(Hook, Name, MFA) -> hook(Hook, Name, MFA) ->
gen_server:call(?SERVER, {hook, Hook, Name, MFA}). gen_server:call(?SERVER, {hook, Hook, Name, MFA}).
%%------------------------------------------------------------------------------
%% @doc Unhook %% @doc Unhook
%% @end
%%------------------------------------------------------------------------------
-spec unhook(Hook :: atom(), Name :: any()) -> ok | {error, any()}. -spec unhook(Hook :: atom(), Name :: any()) -> ok | {error, any()}.
unhook(Hook, Name) -> unhook(Hook, Name) ->
gen_server:call(?SERVER, {unhook, Hook, Name}). gen_server:call(?SERVER, {unhook, Hook, Name}).
%%------------------------------------------------------------------------------
%% @doc Foreach hooks %% @doc Foreach hooks
%% @end
%%------------------------------------------------------------------------------
-spec foreach_hooks(Hook :: atom(), Args :: list()) -> any(). -spec foreach_hooks(Hook :: atom(), Args :: list()) -> any().
foreach_hooks(Hook, Args) -> foreach_hooks(Hook, Args) ->
case ets:lookup(?BROKER_TAB, {hook, Hook}) of case ets:lookup(?BROKER_TAB, {hook, Hook}) of
@ -177,10 +134,7 @@ foreach_hooks(Hook, Args) ->
ok ok
end. end.
%%------------------------------------------------------------------------------
%% @doc Foldl hooks %% @doc Foldl hooks
%% @end
%%------------------------------------------------------------------------------
-spec foldl_hooks(Hook :: atom(), Args :: list(), Acc0 :: any()) -> any(). -spec foldl_hooks(Hook :: atom(), Args :: list(), Acc0 :: any()) -> any().
foldl_hooks(Hook, Args, Acc0) -> foldl_hooks(Hook, Args, Acc0) ->
case ets:lookup(?BROKER_TAB, {hook, Hook}) of case ets:lookup(?BROKER_TAB, {hook, Hook}) of
@ -192,10 +146,7 @@ foldl_hooks(Hook, Args, Acc0) ->
Acc0 Acc0
end. end.
%%------------------------------------------------------------------------------
%% @doc Start a tick timer %% @doc Start a tick timer
%% @end
%%------------------------------------------------------------------------------
start_tick(Msg) -> start_tick(Msg) ->
start_tick(timer:seconds(env(sys_interval)), Msg). start_tick(timer:seconds(env(sys_interval)), Msg).
@ -204,18 +155,15 @@ start_tick(0, _Msg) ->
start_tick(Interval, Msg) when Interval > 0 -> start_tick(Interval, Msg) when Interval > 0 ->
{ok, TRef} = timer:send_interval(Interval, Msg), TRef. {ok, TRef} = timer:send_interval(Interval, Msg), TRef.
%%------------------------------------------------------------------------------
%% @doc Start tick timer %% @doc Start tick timer
%% @end
%%------------------------------------------------------------------------------
stop_tick(undefined) -> stop_tick(undefined) ->
ok; ok;
stop_tick(TRef) -> stop_tick(TRef) ->
timer:cancel(TRef). timer:cancel(TRef).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([]) -> init([]) ->
emqttd:seed_now(), emqttd:seed_now(),
@ -284,9 +232,9 @@ terminate(_Reason, #state{heartbeat = Hb, tick_tref = TRef}) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
create_topic(Topic) -> create_topic(Topic) ->
emqttd_pubsub:create(topic, emqttd_topic:systop(Topic)). emqttd_pubsub:create(topic, emqttd_topic:systop(Topic)).

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd cli
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd cli
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_cli). -module(emqttd_cli).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -60,14 +53,12 @@ load() ->
is_cmd(Fun) -> is_cmd(Fun) ->
not lists:member(Fun, [init, load, module_info]). not lists:member(Fun, [init, load, module_info]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Commands %% Commands
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Node status %% @doc Node status
%% @end
%%------------------------------------------------------------------------------
status([]) -> status([]) ->
{InternalStatus, _ProvidedStatus} = init:get_status(), {InternalStatus, _ProvidedStatus} = init:get_status(),
?PRINT("Node ~p is ~p~n", [node(), InternalStatus]), ?PRINT("Node ~p is ~p~n", [node(), InternalStatus]),
@ -80,10 +71,8 @@ status([]) ->
status(_) -> status(_) ->
?PRINT_CMD("status", "query broker status"). ?PRINT_CMD("status", "query broker status").
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Query broker %% @doc Query broker
%% @end
%%------------------------------------------------------------------------------
broker([]) -> broker([]) ->
Funs = [sysdescr, version, uptime, datetime], Funs = [sysdescr, version, uptime, datetime],
foreach(fun(Fun) -> foreach(fun(Fun) ->
@ -116,10 +105,8 @@ broker(_) ->
{"broker stats", "query broker statistics of clients, topics, subscribers"}, {"broker stats", "query broker statistics of clients, topics, subscribers"},
{"broker metrics", "query broker metrics"}]). {"broker metrics", "query broker metrics"}]).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Cluster with other node %% @doc Cluster with other node
%% @end
%%------------------------------------------------------------------------------
cluster([]) -> cluster([]) ->
Nodes = emqttd_broker:running_nodes(), Nodes = emqttd_broker:running_nodes(),
?PRINT("cluster nodes: ~p~n", [Nodes]); ?PRINT("cluster nodes: ~p~n", [Nodes]);
@ -165,10 +152,8 @@ stop_apps() ->
start_apps() -> start_apps() ->
[application:start(App) || App <- [gproc, esockd, emqttd]]. [application:start(App) || App <- [gproc, esockd, emqttd]].
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Query clients %% @doc Query clients
%% @end
%%------------------------------------------------------------------------------
clients(["list"]) -> clients(["list"]) ->
emqttd_mnesia:dump(ets, mqtt_client, fun print/1); emqttd_mnesia:dump(ets, mqtt_client, fun print/1);
@ -189,10 +174,8 @@ if_client(ClientId, Fun) ->
Client -> Fun(Client) Client -> Fun(Client)
end. end.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Sessions Command %% @doc Sessions Command
%% @end
%%------------------------------------------------------------------------------
sessions(["list"]) -> sessions(["list"]) ->
[sessions(["list", Type]) || Type <- ["persistent", "transient"]]; [sessions(["list", Type]) || Type <- ["persistent", "transient"]];
@ -220,10 +203,8 @@ sessions(_) ->
{"sessions list transient", "list all transient sessions"}, {"sessions list transient", "list all transient sessions"},
{"sessions show <ClientId>", "show a session"}]). {"sessions show <ClientId>", "show a session"}]).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Topics Command %% @doc Topics Command
%% @end
%%------------------------------------------------------------------------------
topics(["list"]) -> topics(["list"]) ->
Print = fun(Topic, Records) -> print(topic, Topic, Records) end, Print = fun(Topic, Records) -> print(topic, Topic, Records) end,
if_could_print(topic, Print); if_could_print(topic, Print);
@ -316,11 +297,8 @@ plugins(_) ->
{"plugins load <Plugin>", "load plugin"}, {"plugins load <Plugin>", "load plugin"},
{"plugins unload <Plugin>", "unload plugin"}]). {"plugins unload <Plugin>", "unload plugin"}]).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Bridges command %% @doc Bridges command
%% @end
%%------------------------------------------------------------------------------
bridges(["list"]) -> bridges(["list"]) ->
foreach(fun({{Node, Topic}, _Pid}) -> foreach(fun({{Node, Topic}, _Pid}) ->
?PRINT("bridge: ~s--~s-->~s~n", [node(), Topic, Node]) ?PRINT("bridge: ~s--~s-->~s~n", [node(), Topic, Node])
@ -376,10 +354,8 @@ parse_opt(bridge, queue, Len) ->
parse_opt(_Cmd, Opt, _Val) -> parse_opt(_Cmd, Opt, _Val) ->
?PRINT("Bad Option: ~s~n", [Opt]). ?PRINT("Bad Option: ~s~n", [Opt]).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc vm command %% @doc vm command
%% @end
%%------------------------------------------------------------------------------
vm([]) -> vm([]) ->
vm(["all"]); vm(["all"]);
@ -410,20 +386,16 @@ vm(_) ->
{"vm process", "query process of erlang vm"}, {"vm process", "query process of erlang vm"},
{"vm io", "queue io of erlang vm"}]). {"vm io", "queue io of erlang vm"}]).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc mnesia Command %% @doc mnesia Command
%% @end
%%------------------------------------------------------------------------------
mnesia([]) -> mnesia([]) ->
mnesia:system_info(); mnesia:system_info();
mnesia(_) -> mnesia(_) ->
?PRINT_CMD("mnesia", "mnesia system info"). ?PRINT_CMD("mnesia", "mnesia system info").
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Trace Command %% @doc Trace Command
%% @end
%%------------------------------------------------------------------------------
trace(["list"]) -> trace(["list"]) ->
foreach(fun({{Who, Name}, LogFile}) -> foreach(fun({{Who, Name}, LogFile}) ->
?PRINT("trace ~s ~s -> ~s~n", [Who, Name, LogFile]) ?PRINT("trace ~s ~s -> ~s~n", [Who, Name, LogFile])
@ -464,10 +436,8 @@ trace_off(Who, Name) ->
?PRINT("stop to trace ~s ~s error: ~p.~n", [Who, Name, Error]) ?PRINT("stop to trace ~s ~s error: ~p.~n", [Who, Name, Error])
end. end.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% @doc Listeners Command %% @doc Listeners Command
%% @end
%%------------------------------------------------------------------------------
listeners([]) -> listeners([]) ->
foreach(fun({{Protocol, Port}, Pid}) -> foreach(fun({{Protocol, Port}, Pid}) ->
Info = [{acceptors, esockd:get_acceptors(Pid)}, Info = [{acceptors, esockd:get_acceptors(Pid)},
@ -531,6 +501,5 @@ format(subscriptions, List) ->
format(_, Val) -> format(_, Val) ->
Val. Val.
bin(S) when is_list(S) -> list_to_binary(S); bin(S) -> iolist_to_binary(S).
bin(B) when is_binary(B) -> B.

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc MQTT Client Connection
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc MQTT Client Connection
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_client). -module(emqttd_client).
-behaviour(gen_server). -behaviour(gen_server).
@ -228,9 +221,9 @@ terminate(Reason, #client_state{connection = Connection,
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
with_proto_state(Fun, State = #client_state{proto_state = ProtoState}) -> with_proto_state(Fun, State = #client_state{proto_state = ProtoState}) ->
{ok, ProtoState1} = Fun(ProtoState), {ok, ProtoState1} = Fun(ProtoState),

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc MQTT Client Manager
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc MQTT Client Manager
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_cm). -module(emqttd_cm).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -47,14 +40,11 @@
-define(POOL, ?MODULE). -define(POOL, ?MODULE).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Start Client Manager %% @doc Start Client Manager
%% @end
%%------------------------------------------------------------------------------
-spec start_link(Pool, Id, StatsFun) -> {ok, pid()} | ignore | {error, any()} when -spec start_link(Pool, Id, StatsFun) -> {ok, pid()} | ignore | {error, any()} when
Pool :: atom(), Pool :: atom(),
Id :: pos_integer(), Id :: pos_integer(),
@ -62,10 +52,7 @@
start_link(Pool, Id, StatsFun) -> start_link(Pool, Id, StatsFun) ->
gen_server2:start_link(?MODULE, [Pool, Id, StatsFun], []). gen_server2:start_link(?MODULE, [Pool, Id, StatsFun], []).
%%------------------------------------------------------------------------------
%% @doc Lookup Client by ClientId %% @doc Lookup Client by ClientId
%% @end
%%------------------------------------------------------------------------------
-spec lookup(ClientId :: binary()) -> mqtt_client() | undefined. -spec lookup(ClientId :: binary()) -> mqtt_client() | undefined.
lookup(ClientId) when is_binary(ClientId) -> lookup(ClientId) when is_binary(ClientId) ->
case ets:lookup(mqtt_client, ClientId) of case ets:lookup(mqtt_client, ClientId) of
@ -73,10 +60,7 @@ lookup(ClientId) when is_binary(ClientId) ->
[] -> undefined [] -> undefined
end. end.
%%------------------------------------------------------------------------------
%% @doc Lookup client pid by clientId %% @doc Lookup client pid by clientId
%% @end
%%------------------------------------------------------------------------------
-spec lookup_proc(ClientId :: binary()) -> pid() | undefined. -spec lookup_proc(ClientId :: binary()) -> pid() | undefined.
lookup_proc(ClientId) when is_binary(ClientId) -> lookup_proc(ClientId) when is_binary(ClientId) ->
try ets:lookup_element(mqtt_client, ClientId, #mqtt_client.client_pid) try ets:lookup_element(mqtt_client, ClientId, #mqtt_client.client_pid)
@ -84,27 +68,21 @@ lookup_proc(ClientId) when is_binary(ClientId) ->
error:badarg -> undefined error:badarg -> undefined
end. end.
%%------------------------------------------------------------------------------
%% @doc Register ClientId with Pid. %% @doc Register ClientId with Pid.
%% @end
%%------------------------------------------------------------------------------
-spec register(Client :: mqtt_client()) -> ok. -spec register(Client :: mqtt_client()) -> ok.
register(Client = #mqtt_client{client_id = ClientId}) -> register(Client = #mqtt_client{client_id = ClientId}) ->
CmPid = gproc_pool:pick_worker(?POOL, ClientId), CmPid = gproc_pool:pick_worker(?POOL, ClientId),
gen_server2:cast(CmPid, {register, Client}). gen_server2:cast(CmPid, {register, Client}).
%%------------------------------------------------------------------------------
%% @doc Unregister clientId with pid. %% @doc Unregister clientId with pid.
%% @end
%%------------------------------------------------------------------------------
-spec unregister(ClientId :: binary()) -> ok. -spec unregister(ClientId :: binary()) -> ok.
unregister(ClientId) when is_binary(ClientId) -> unregister(ClientId) when is_binary(ClientId) ->
CmPid = gproc_pool:pick_worker(?POOL, ClientId), CmPid = gproc_pool:pick_worker(?POOL, ClientId),
gen_server2:cast(CmPid, {unregister, ClientId, self()}). gen_server2:cast(CmPid, {unregister, ClientId, self()}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([Pool, Id, StatsFun]) -> init([Pool, Id, StatsFun]) ->
?GPROC_POOL(join, Pool, Id), ?GPROC_POOL(join, Pool, Id),
@ -174,9 +152,9 @@ terminate(_Reason, #state{pool = Pool, id = Id}) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
monitor_client(ClientId, Pid, State = #state{monitors = Monitors}) -> monitor_client(ClientId, Pid, State = #state{monitors = Monitors}) ->
MRef = erlang:monitor(process, Pid), MRef = erlang:monitor(process, Pid),

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Client Manager Supervisor.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Client Manager Supervisor.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_cm_sup). -module(emqttd_cm_sup).
-behaviour(supervisor). -behaviour(supervisor).

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd control
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd control
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_ctl). -module(emqttd_ctl).
-behaviour(gen_server). -behaviour(gen_server).
@ -47,36 +40,26 @@
-define(CMD_TAB, mqttd_ctl_cmd). -define(CMD_TAB, mqttd_ctl_cmd).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
start_link() -> start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
%%------------------------------------------------------------------------------
%% @doc Register a command %% @doc Register a command
%% @end
%%------------------------------------------------------------------------------
-spec register_cmd(atom(), {module(), atom()}, list()) -> ok. -spec register_cmd(atom(), {module(), atom()}, list()) -> ok.
register_cmd(Cmd, MF, Opts) -> register_cmd(Cmd, MF, Opts) ->
cast({register_cmd, Cmd, MF, Opts}). cast({register_cmd, Cmd, MF, Opts}).
%%------------------------------------------------------------------------------
%% @doc Unregister a command %% @doc Unregister a command
%% @end
%%------------------------------------------------------------------------------
-spec unregister_cmd(atom()) -> ok. -spec unregister_cmd(atom()) -> ok.
unregister_cmd(Cmd) -> unregister_cmd(Cmd) ->
cast({unregister_cmd, Cmd}). cast({unregister_cmd, Cmd}).
cast(Msg) -> cast(Msg) -> gen_server:cast(?SERVER, Msg).
gen_server:cast(?SERVER, Msg).
%%------------------------------------------------------------------------------
%% @doc Run a command %% @doc Run a command
%% @end
%%------------------------------------------------------------------------------
run([]) -> usage(); run([]) -> usage();
run(["help"]) -> usage(); run(["help"]) -> usage();
@ -88,18 +71,15 @@ run([CmdS|Args]) ->
[] -> usage() [] -> usage()
end. end.
%%------------------------------------------------------------------------------
%% @doc Usage %% @doc Usage
%% @end
%%------------------------------------------------------------------------------
usage() -> usage() ->
?PRINT("Usage: ~s~n", [?MODULE]), ?PRINT("Usage: ~s~n", [?MODULE]),
[begin ?PRINT("~80..-s~n", [""]), Mod:Cmd(usage) end [begin ?PRINT("~80..-s~n", [""]), Mod:Cmd(usage) end
|| {_, {Mod, Cmd}, _} <- ets:tab2list(?CMD_TAB)]. || {_, {Mod, Cmd}, _} <- ets:tab2list(?CMD_TAB)].
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([]) -> init([]) ->
ets:new(?CMD_TAB, [ordered_set, named_table, protected]), ets:new(?CMD_TAB, [ordered_set, named_table, protected]),
@ -134,9 +114,9 @@ terminate(_Reason, _State) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal Function Definitions %% Internal Function Definitions
%%%============================================================================= %%--------------------------------------------------------------------
noreply(State) -> noreply(State) ->
{noreply, State, hibernate}. {noreply, State, hibernate}.
@ -144,4 +124,3 @@ noreply(State) ->
next_seq(State = #state{seq = Seq}) -> next_seq(State = #state{seq = Seq}) ->
State#state{seq = Seq + 1}. State#state{seq = Seq + 1}.

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd distribution functions
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd distribution functions
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_dist). -module(emqttd_dist).
-import(lists, [concat/1]). -import(lists, [concat/1]).

View File

@ -1,35 +1,28 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd gen_mod behaviour
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd gen_mod behaviour
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_gen_mod). -module(emqttd_gen_mod).
-include("emqttd.hrl"). -include("emqttd.hrl").
-ifdef(use_specs). -ifdef(use_specs).
-callback load(Opts :: any()) -> {ok, State :: any()}. -callback load(Opts :: any()) -> ok | {error, any()}.
-callback unload(State :: any()) -> any(). -callback unload(State :: any()) -> any().

View File

@ -1,42 +1,34 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Generate global unique id for mqtt message.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %%
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% --------------------------------------------------------
%%% SOFTWARE. %% | Timestamp | NodeID + PID | Sequence |
%%%----------------------------------------------------------------------------- %% |<------- 64bits ------->|<--- 48bits --->|<- 16bits ->|
%%% @doc %% --------------------------------------------------------
%%% %%
%%% Generate global unique id for mqtt message. %% 1. Timestamp: erlang:system_time if Erlang >= R18, otherwise os:timestamp
%%% %% 2. NodeId: encode node() to 2 bytes integer
%%% -------------------------------------------------------- %% 3. Pid: encode pid to 4 bytes integer
%%% | Timestamp | NodeID + PID | Sequence | %% 4. Sequence: 2 bytes sequence in one process
%%% |<------- 64bits ------->|<--- 48bits --->|<- 16bits ->| %%
%%% -------------------------------------------------------- %% @end
%%% %%
%%% 1. Timestamp: erlang:system_time if Erlang >= R18, otherwise os:timestamp %% @author Feng Lee <feng@emqtt.io>
%%% 2. NodeId: encode node() to 2 bytes integer
%%% 3. Pid: encode pid to 4 bytes integer
%%% 4. Sequence: 2 bytes sequence in one process
%%%
%%% @end
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_guid). -module(emqttd_guid).
-export([gen/0, new/0, timestamp/1]). -export([gen/0, new/0, timestamp/1]).
@ -45,10 +37,7 @@
-type guid() :: <<_:128>>. -type guid() :: <<_:128>>.
%%------------------------------------------------------------------------------
%% @doc Generate a global unique id. %% @doc Generate a global unique id.
%% @end
%%------------------------------------------------------------------------------
-spec gen() -> guid(). -spec gen() -> guid().
gen() -> gen() ->
Guid = case get(guid) of Guid = case get(guid) of

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd http publish API and websocket client.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd http publish API and websocket client.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_http). -module(emqttd_http).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -47,9 +40,10 @@ handle_request('GET', "/status", Req) ->
[node(), InternalStatus, AppStatus]), [node(), InternalStatus, AppStatus]),
Req:ok({"text/plain", iolist_to_binary(Status)}); Req:ok({"text/plain", iolist_to_binary(Status)});
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% HTTP Publish API %% HTTP Publish API
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
handle_request('POST', "/mqtt/publish", Req) -> handle_request('POST', "/mqtt/publish", Req) ->
Params = mochiweb_request:parse_post(Req), Params = mochiweb_request:parse_post(Req),
lager:info("HTTP Publish: ~p", [Params]), lager:info("HTTP Publish: ~p", [Params]),
@ -74,9 +68,9 @@ handle_request('POST', "/mqtt/publish", Req) ->
Req:respond({401, [], <<"Fobbiden">>}) Req:respond({401, [], <<"Fobbiden">>})
end; end;
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% MQTT Over WebSocket %% MQTT Over WebSocket
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
handle_request('GET', "/mqtt", Req) -> handle_request('GET', "/mqtt", Req) ->
lager:info("WebSocket Connection from: ~s", [Req:get(peer)]), lager:info("WebSocket Connection from: ~s", [Req:get(peer)]),
Upgrade = Req:get_header_value("Upgrade"), Upgrade = Req:get_header_value("Upgrade"),
@ -92,9 +86,10 @@ handle_request('GET', "/mqtt", Req) ->
Req:respond({400, [], <<"Bad WebSocket Protocol">>}) Req:respond({400, [], <<"Bad WebSocket Protocol">>})
end; end;
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% Get static files %% Get static files
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
handle_request('GET', "/" ++ File, Req) -> handle_request('GET', "/" ++ File, Req) ->
lager:info("HTTP GET File: ~s", [File]), lager:info("HTTP GET File: ~s", [File]),
mochiweb_request:serve_file(File, docroot(), Req); mochiweb_request:serve_file(File, docroot(), Req);
@ -103,9 +98,9 @@ handle_request(Method, Path, Req) ->
lager:error("Unexpected HTTP Request: ~s ~s", [Method, Path]), lager:error("Unexpected HTTP Request: ~s ~s", [Method, Path]),
Req:not_found(). Req:not_found().
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% basic authorization %% basic authorization
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
authorized(Req) -> authorized(Req) ->
case Req:get_header_value("Authorization") of case Req:get_header_value("Authorization") of
undefined -> undefined ->

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc client keepalive
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc client keepalive
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_keepalive). -module(emqttd_keepalive).
-export([start/3, check/1, cancel/1]). -export([start/3, check/1, cancel/1]).
@ -33,10 +26,7 @@
-type keepalive() :: #keepalive{}. -type keepalive() :: #keepalive{}.
%%------------------------------------------------------------------------------
%% @doc Start a keepalive %% @doc Start a keepalive
%% @end
%%------------------------------------------------------------------------------
-spec start(fun(), integer(), any()) -> undefined | keepalive(). -spec start(fun(), integer(), any()) -> undefined | keepalive().
start(_, 0, _) -> start(_, 0, _) ->
undefined; undefined;
@ -46,10 +36,7 @@ start(StatFun, TimeoutSec, TimeoutMsg) ->
tsec = TimeoutSec, tmsg = TimeoutMsg, tsec = TimeoutSec, tmsg = TimeoutMsg,
tref = timer(TimeoutSec, TimeoutMsg)}. tref = timer(TimeoutSec, TimeoutMsg)}.
%%------------------------------------------------------------------------------
%% @doc Check keepalive, called when timeout. %% @doc Check keepalive, called when timeout.
%% @end
%%------------------------------------------------------------------------------
-spec check(keepalive()) -> {ok, keepalive()} | {error, any()}. -spec check(keepalive()) -> {ok, keepalive()} | {error, any()}.
check(KeepAlive = #keepalive{statfun = StatFun, statval = LastVal, repeat = Repeat}) -> check(KeepAlive = #keepalive{statfun = StatFun, statval = LastVal, repeat = Repeat}) ->
case StatFun() of case StatFun() of
@ -68,10 +55,7 @@ check(KeepAlive = #keepalive{statfun = StatFun, statval = LastVal, repeat = Repe
resume(KeepAlive = #keepalive{tsec = TimeoutSec, tmsg = TimeoutMsg}) -> resume(KeepAlive = #keepalive{tsec = TimeoutSec, tmsg = TimeoutMsg}) ->
KeepAlive#keepalive{tref = timer(TimeoutSec, TimeoutMsg)}. KeepAlive#keepalive{tref = timer(TimeoutSec, TimeoutMsg)}.
%%------------------------------------------------------------------------------
%% @doc Cancel Keepalive %% @doc Cancel Keepalive
%% @end
%%------------------------------------------------------------------------------
-spec cancel(keepalive()) -> ok. -spec cancel(keepalive()) -> ok.
cancel(#keepalive{tref = TRef}) -> cancel(#keepalive{tref = TRef}) ->
cancel(TRef); cancel(TRef);

View File

@ -1,33 +0,0 @@
%%%-----------------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved.
%%%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy
%%% of this software and associated documentation files (the "Software"), to deal
%%% in the Software without restriction, including without limitation the rights
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%%% copies of the Software, and to permit persons to whom the Software is
%%% furnished to do so, subject to the following conditions:
%%%
%%% The above copyright notice and this permission notice shall be included in all
%%% copies or substantial portions of the Software.
%%%
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc
%%% emqttd log trace.
%%%
%%% @end
%%%-----------------------------------------------------------------------------
%% TODO: issue #103
%% 0.12.0 ???
-module(emqttd_log).
%%TODO: Hooks to log???

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc MQTT Message Functions
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc MQTT Message Functions
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_message). -module(emqttd_message).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -35,10 +28,7 @@
-export([format/1]). -export([format/1]).
%%------------------------------------------------------------------------------
%% @doc Make a message %% @doc Make a message
%% @end
%%------------------------------------------------------------------------------
-spec make(From, Topic, Payload) -> mqtt_message() when -spec make(From, Topic, Payload) -> mqtt_message() when
From :: atom() | binary(), From :: atom() | binary(),
Topic :: binary(), Topic :: binary(),
@ -62,10 +52,7 @@ make(From, Qos, Topic, Payload) ->
payload = Payload, payload = Payload,
timestamp = os:timestamp()}. timestamp = os:timestamp()}.
%%------------------------------------------------------------------------------
%% @doc Message from Packet %% @doc Message from Packet
%% @end
%%------------------------------------------------------------------------------
-spec from_packet(mqtt_packet()) -> mqtt_message(). -spec from_packet(mqtt_packet()) -> mqtt_message().
from_packet(#mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH, from_packet(#mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH,
retain = Retain, retain = Retain,
@ -106,10 +93,7 @@ msgid(?QOS_0) ->
msgid(Qos) when Qos =:= ?QOS_1 orelse Qos =:= ?QOS_2 -> msgid(Qos) when Qos =:= ?QOS_1 orelse Qos =:= ?QOS_2 ->
emqttd_guid:gen(). emqttd_guid:gen().
%%------------------------------------------------------------------------------
%% @doc Message to packet %% @doc Message to packet
%% @end
%%------------------------------------------------------------------------------
-spec to_packet(mqtt_message()) -> mqtt_packet(). -spec to_packet(mqtt_message()) -> mqtt_packet().
to_packet(#mqtt_message{pktid = PkgId, to_packet(#mqtt_message{pktid = PkgId,
qos = Qos, qos = Qos,
@ -130,10 +114,7 @@ to_packet(#mqtt_message{pktid = PkgId,
}, },
payload = Payload}. payload = Payload}.
%%------------------------------------------------------------------------------
%% @doc set dup, retain flag %% @doc set dup, retain flag
%% @end
%%------------------------------------------------------------------------------
-spec set_flag(mqtt_message()) -> mqtt_message(). -spec set_flag(mqtt_message()) -> mqtt_message().
set_flag(Msg) -> set_flag(Msg) ->
Msg#mqtt_message{dup = true, retain = true}. Msg#mqtt_message{dup = true, retain = true}.
@ -147,10 +128,7 @@ set_flag(retain, Msg = #mqtt_message{retain = false}) ->
Msg#mqtt_message{retain = true}; Msg#mqtt_message{retain = true};
set_flag(Flag, Msg) when Flag =:= dup orelse Flag =:= retain -> Msg. set_flag(Flag, Msg) when Flag =:= dup orelse Flag =:= retain -> Msg.
%%------------------------------------------------------------------------------
%% @doc Unset dup, retain flag %% @doc Unset dup, retain flag
%% @end
%%------------------------------------------------------------------------------
-spec unset_flag(mqtt_message()) -> mqtt_message(). -spec unset_flag(mqtt_message()) -> mqtt_message().
unset_flag(Msg) -> unset_flag(Msg) ->
Msg#mqtt_message{dup = false, retain = false}. Msg#mqtt_message{dup = false, retain = false}.
@ -162,10 +140,7 @@ unset_flag(retain, Msg = #mqtt_message{retain = true}) ->
Msg#mqtt_message{retain = false}; Msg#mqtt_message{retain = false};
unset_flag(Flag, Msg) when Flag =:= dup orelse Flag =:= retain -> Msg. unset_flag(Flag, Msg) when Flag =:= dup orelse Flag =:= retain -> Msg.
%%------------------------------------------------------------------------------
%% @doc Format MQTT Message %% @doc Format MQTT Message
%% @end
%%------------------------------------------------------------------------------
format(#mqtt_message{msgid = MsgId, pktid = PktId, from = From, format(#mqtt_message{msgid = MsgId, pktid = PktId, from = From,
qos = Qos, retain = Retain, dup = Dup, topic =Topic}) -> qos = Qos, retain = Retain, dup = Dup, topic =Topic}) ->
io_lib:format("Message(Q~p, R~p, D~p, MsgId=~p, PktId=~p, From=~s, Topic=~s)", io_lib:format("Message(Q~p, R~p, D~p, MsgId=~p, PktId=~p, From=~s, Topic=~s)",

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd metrics. responsible for collecting broker metrics
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd metrics. responsible for collecting broker metrics
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_metrics). -module(emqttd_metrics).
-behaviour(gen_server). -behaviour(gen_server).
@ -97,22 +90,16 @@
{counter, 'messages/dropped'} % Messages dropped {counter, 'messages/dropped'} % Messages dropped
]). ]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Start metrics server %% @doc Start metrics server
%% @end
%%------------------------------------------------------------------------------
-spec start_link() -> {ok, pid()} | ignore | {error, any()}. -spec start_link() -> {ok, pid()} | ignore | {error, any()}.
start_link() -> start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
%%------------------------------------------------------------------------------
%% @doc Count packets received. %% @doc Count packets received.
%% @end
%%------------------------------------------------------------------------------
-spec received(mqtt_packet()) -> ok. -spec received(mqtt_packet()) -> ok.
received(Packet) -> received(Packet) ->
inc('packets/received'), inc('packets/received'),
@ -150,10 +137,7 @@ qos_received(?QOS_1) ->
qos_received(?QOS_2) -> qos_received(?QOS_2) ->
inc('messages/qos2/received'). inc('messages/qos2/received').
%%------------------------------------------------------------------------------
%% @doc Count packets received. Will not count $SYS PUBLISH. %% @doc Count packets received. Will not count $SYS PUBLISH.
%% @end
%%------------------------------------------------------------------------------
-spec sent(mqtt_packet()) -> ok. -spec sent(mqtt_packet()) -> ok.
sent(?PUBLISH_PACKET(_Qos, <<"$SYS/", _/binary>>, _, _)) -> sent(?PUBLISH_PACKET(_Qos, <<"$SYS/", _/binary>>, _, _)) ->
ignore; ignore;
@ -191,10 +175,7 @@ qos_sent(?QOS_1) ->
qos_sent(?QOS_2) -> qos_sent(?QOS_2) ->
inc('messages/qos2/sent'). inc('messages/qos2/sent').
%%------------------------------------------------------------------------------
%% @doc Get all metrics %% @doc Get all metrics
%% @end
%%------------------------------------------------------------------------------
-spec all() -> [{atom(), non_neg_integer()}]. -spec all() -> [{atom(), non_neg_integer()}].
all() -> all() ->
maps:to_list( maps:to_list(
@ -206,26 +187,17 @@ all() ->
end end
end, #{}, ?METRIC_TAB)). end, #{}, ?METRIC_TAB)).
%%------------------------------------------------------------------------------
%% @doc Get metric value %% @doc Get metric value
%% @end
%%------------------------------------------------------------------------------
-spec value(atom()) -> non_neg_integer(). -spec value(atom()) -> non_neg_integer().
value(Metric) -> value(Metric) ->
lists:sum(ets:select(?METRIC_TAB, [{{{Metric, '_'}, '$1'}, [], ['$1']}])). lists:sum(ets:select(?METRIC_TAB, [{{{Metric, '_'}, '$1'}, [], ['$1']}])).
%%------------------------------------------------------------------------------
%% @doc Increase counter %% @doc Increase counter
%% @end
%%------------------------------------------------------------------------------
-spec inc(atom()) -> non_neg_integer(). -spec inc(atom()) -> non_neg_integer().
inc(Metric) -> inc(Metric) ->
inc(counter, Metric, 1). inc(counter, Metric, 1).
%%------------------------------------------------------------------------------
%% @doc Increase metric value %% @doc Increase metric value
%% @end
%%------------------------------------------------------------------------------
-spec inc({counter | gauge, atom()} | atom(), pos_integer()) -> non_neg_integer(). -spec inc({counter | gauge, atom()} | atom(), pos_integer()) -> non_neg_integer().
inc({gauge, Metric}, Val) -> inc({gauge, Metric}, Val) ->
inc(gauge, Metric, Val); inc(gauge, Metric, Val);
@ -234,53 +206,38 @@ inc({counter, Metric}, Val) ->
inc(Metric, Val) when is_atom(Metric) -> inc(Metric, Val) when is_atom(Metric) ->
inc(counter, Metric, Val). inc(counter, Metric, Val).
%%------------------------------------------------------------------------------
%% @doc Increase metric value %% @doc Increase metric value
%% @end
%%------------------------------------------------------------------------------
-spec inc(counter | gauge, atom(), pos_integer()) -> pos_integer(). -spec inc(counter | gauge, atom(), pos_integer()) -> pos_integer().
inc(gauge, Metric, Val) -> inc(gauge, Metric, Val) ->
ets:update_counter(?METRIC_TAB, key(gauge, Metric), {2, Val}); ets:update_counter(?METRIC_TAB, key(gauge, Metric), {2, Val});
inc(counter, Metric, Val) -> inc(counter, Metric, Val) ->
ets:update_counter(?METRIC_TAB, key(counter, Metric), {2, Val}). ets:update_counter(?METRIC_TAB, key(counter, Metric), {2, Val}).
%%------------------------------------------------------------------------------
%% @doc Decrease metric value %% @doc Decrease metric value
%% @end
%%------------------------------------------------------------------------------
-spec dec(gauge, atom()) -> integer(). -spec dec(gauge, atom()) -> integer().
dec(gauge, Metric) -> dec(gauge, Metric) ->
dec(gauge, Metric, 1). dec(gauge, Metric, 1).
%%------------------------------------------------------------------------------
%% @doc Decrease metric value %% @doc Decrease metric value
%% @end
%%------------------------------------------------------------------------------
-spec dec(gauge, atom(), pos_integer()) -> integer(). -spec dec(gauge, atom(), pos_integer()) -> integer().
dec(gauge, Metric, Val) -> dec(gauge, Metric, Val) ->
ets:update_counter(?METRIC_TAB, key(gauge, Metric), {2, -Val}). ets:update_counter(?METRIC_TAB, key(gauge, Metric), {2, -Val}).
%%------------------------------------------------------------------------------
%% @doc Set metric value %% @doc Set metric value
%% @end
%%------------------------------------------------------------------------------
set(Metric, Val) when is_atom(Metric) -> set(Metric, Val) when is_atom(Metric) ->
set(gauge, Metric, Val). set(gauge, Metric, Val).
set(gauge, Metric, Val) -> set(gauge, Metric, Val) ->
ets:insert(?METRIC_TAB, {key(gauge, Metric), Val}). ets:insert(?METRIC_TAB, {key(gauge, Metric), Val}).
%%------------------------------------------------------------------------------
%% @doc Metric Key %% @doc Metric Key
%% @end
%%------------------------------------------------------------------------------
key(gauge, Metric) -> key(gauge, Metric) ->
{Metric, 0}; {Metric, 0};
key(counter, Metric) -> key(counter, Metric) ->
{Metric, erlang:system_info(scheduler_id)}. {Metric, erlang:system_info(scheduler_id)}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([]) -> init([]) ->
emqttd:seed_now(), emqttd:seed_now(),
@ -314,9 +271,9 @@ terminate(_Reason, #state{tick_tref = TRef}) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
publish(Metric, Val) -> publish(Metric, Val) ->
Payload = emqttd_util:integer_to_binary(Val), Payload = emqttd_util:integer_to_binary(Val),

View File

@ -1,28 +1,22 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% TODO: refactor this module
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @doc emqttd mnesia
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% @author Feng Lee <feng@emqtt.io>
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd mnesia
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_mnesia). -module(emqttd_mnesia).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -46,13 +40,8 @@ start() ->
init_tables(), init_tables(),
wait_for_tables(). wait_for_tables().
%%------------------------------------------------------------------------------
%% @doc
%% @private %% @private
%% init mnesia schema. %% @doc Init mnesia schema.
%%
%% @end
%%------------------------------------------------------------------------------
init_schema() -> init_schema() ->
case mnesia:system_info(extra_db_nodes) of case mnesia:system_info(extra_db_nodes) of
[] -> [] ->
@ -62,13 +51,8 @@ init_schema() ->
ok ok
end. end.
%%------------------------------------------------------------------------------
%% @doc
%% @private %% @private
%% init mnesia tables. %% @doc Init mnesia tables.
%%
%% @end
%%------------------------------------------------------------------------------
init_tables() -> init_tables() ->
case mnesia:system_info(extra_db_nodes) of case mnesia:system_info(extra_db_nodes) of
[] -> [] ->
@ -77,13 +61,8 @@ init_tables() ->
copy_tables() copy_tables()
end. end.
%%------------------------------------------------------------------------------
%% @doc
%% @private %% @private
%% create tables. %% @doc create tables.
%%
%% @end
%%------------------------------------------------------------------------------
create_tables() -> create_tables() ->
emqttd_util:apply_module_attributes(boot_mnesia). emqttd_util:apply_module_attributes(boot_mnesia).
@ -95,13 +74,8 @@ create_table(Table, Attrs) ->
Error -> Error Error -> Error
end. end.
%%------------------------------------------------------------------------------
%% @doc
%% @private %% @private
%% copy tables. %% @doc copy tables.
%%
%% @end
%%------------------------------------------------------------------------------
copy_tables() -> copy_tables() ->
emqttd_util:apply_module_attributes(copy_mnesia). emqttd_util:apply_module_attributes(copy_mnesia).
@ -113,24 +87,15 @@ copy_table(Table) ->
{aborted, Error} -> Error {aborted, Error} -> Error
end. end.
%%------------------------------------------------------------------------------
%% @doc
%% @private %% @private
%% wait for tables. %% @doc wait for tables.
%% wait_for_tables() ->
%% @end
%%------------------------------------------------------------------------------
wait_for_tables() ->
%% io:format("mnesia wait_for_tables: ~p~n", [mnesia:system_info(local_tables)]), %% io:format("mnesia wait_for_tables: ~p~n", [mnesia:system_info(local_tables)]),
mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity). mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity).
%%------------------------------------------------------------------------------ %% TODO: should move to cluster.
%% @doc
%% @private %% @private
%% Simple cluster with another nodes. %% @doc Simple cluster with another nodes.
%%
%% @end
%%------------------------------------------------------------------------------
cluster(Node) -> cluster(Node) ->
%% stop mnesia %% stop mnesia
mnesia:stop(), mnesia:stop(),

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd presence management module
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd presence management module
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_mod_presence). -module(emqttd_mod_presence).
-behaviour(emqttd_gen_mod). -behaviour(emqttd_gen_mod).
@ -38,7 +31,7 @@ load(Opts) ->
{?MODULE, client_connected, [Opts]}), {?MODULE, client_connected, [Opts]}),
emqttd_broker:hook('client.disconnected', {?MODULE, client_disconnected}, emqttd_broker:hook('client.disconnected', {?MODULE, client_disconnected},
{?MODULE, client_disconnected, [Opts]}), {?MODULE, client_disconnected, [Opts]}),
{ok, Opts}. ok.
client_connected(ConnAck, #mqtt_client{client_id = ClientId, client_connected(ConnAck, #mqtt_client{client_id = ClientId,
username = Username, username = Username,
@ -85,4 +78,3 @@ reason(Reason) when is_atom(Reason) -> Reason;
reason({Error, _}) when is_atom(Error) -> Error; reason({Error, _}) when is_atom(Error) -> Error;
reason(_) -> internal_error. reason(_) -> internal_error.

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd rewrite module
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd rewrite module
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_mod_rewrite). -module(emqttd_mod_rewrite).
-behaviour(emqttd_gen_mod). -behaviour(emqttd_gen_mod).
@ -33,9 +26,9 @@
-export([rewrite/3, rewrite/4]). -export([rewrite/3, rewrite/4]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
load(Opts) -> load(Opts) ->
File = proplists:get_value(file, Opts), File = proplists:get_value(file, Opts),
@ -47,7 +40,7 @@ load(Opts) ->
{?MODULE, rewrite, [unsubscribe, Sections]}), {?MODULE, rewrite, [unsubscribe, Sections]}),
emqttd_broker:hook('message.publish', {?MODULE, rewrite_publish}, emqttd_broker:hook('message.publish', {?MODULE, rewrite_publish},
{?MODULE, rewrite, [publish, Sections]}), {?MODULE, rewrite, [publish, Sections]}),
{ok, Sections}. ok.
rewrite(_ClientId, TopicTable, subscribe, Sections) -> rewrite(_ClientId, TopicTable, subscribe, Sections) ->
lager:info("rewrite subscribe: ~p", [TopicTable]), lager:info("rewrite subscribe: ~p", [TopicTable]),
@ -84,9 +77,9 @@ unload(_) ->
emqttd_broker:unhook('client.unsubscribe',{?MODULE, rewrite_unsubscribe}), emqttd_broker:unhook('client.unsubscribe',{?MODULE, rewrite_unsubscribe}),
emqttd_broker:unhook('message.publish', {?MODULE, rewrite_publish}). emqttd_broker:unhook('message.publish', {?MODULE, rewrite_publish}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
compile(Sections) -> compile(Sections) ->
C = fun({rewrite, Re, Dest}) -> C = fun({rewrite, Re, Dest}) ->

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Subscription from Broker Side
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Subscription from Broker Side
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_mod_subscription). -module(emqttd_mod_subscription).
-behaviour(emqttd_gen_mod). -behaviour(emqttd_gen_mod).
@ -44,7 +37,7 @@ load(Opts) ->
State = #state{topics = Topics, stored = lists:member(stored, Opts)}, 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, [State]}), {?MODULE, client_connected, [State]}),
{ok, State}. ok.
client_connected(?CONNACK_ACCEPT, #mqtt_client{client_id = ClientId, client_connected(?CONNACK_ACCEPT, #mqtt_client{client_id = ClientId,
client_pid = ClientPid, client_pid = ClientPid,

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd module supervisor.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd module supervisor.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_mod_sup). -module(emqttd_mod_sup).
-behaviour(supervisor). -behaviour(supervisor).
@ -38,9 +31,9 @@
%% Helper macro for declaring children of supervisor %% Helper macro for declaring children of supervisor
-define(CHILD(Mod, Type), {Mod, {Mod, start_link, []}, permanent, 5000, Type, [Mod]}). -define(CHILD(Mod, Type), {Mod, {Mod, start_link, []}, permanent, 5000, Type, [Mod]}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
start_link() -> start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []). supervisor:start_link({local, ?MODULE}, ?MODULE, []).
@ -55,10 +48,11 @@ start_child(ChildSpec) when is_tuple(ChildSpec) ->
start_child(Mod, Type) when is_atom(Mod) and is_atom(Type) -> start_child(Mod, Type) when is_atom(Mod) and is_atom(Type) ->
supervisor:start_child(?MODULE, ?CHILD(Mod, Type)). supervisor:start_child(?MODULE, ?CHILD(Mod, Type)).
%%%=============================================================================
%%% Supervisor callbacks %%--------------------------------------------------------------------
%%%============================================================================= %% Supervisor callbacks
%%--------------------------------------------------------------------
init([]) -> init([]) ->
{ok, {{one_for_one, 10, 3600}, []}}. {ok, {{one_for_one, 10, 100}, []}}.

View File

@ -1,55 +1,47 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc A Simple in-memory message queue.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %%
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% Notice that MQTT is not an enterprise messaging queue. MQTT assume that client
%%% SOFTWARE. %% should be online in most of the time.
%%%----------------------------------------------------------------------------- %%
%%% @doc %% This module implements a simple in-memory queue for MQTT persistent session.
%%% %%
%%% A Simple in-memory message queue. %% If the broker restarted or crashed, all the messages queued will be gone.
%%% %%
%%% Notice that MQTT is not an enterprise messaging queue. MQTT assume that client %% Concept of Message Queue and Inflight Window:
%%% should be online in most of the time. %%
%%% %% |<----------------- Max Len ----------------->|
%%% This module implements a simple in-memory queue for MQTT persistent session. %% -----------------------------------------------
%%% %% IN -> | Messages Queue | Inflight Window | -> Out
%%% If the broker restarted or crashed, all the messages queued will be gone. %% -----------------------------------------------
%%% %% |<--- Win Size --->|
%%% Concept of Message Queue and Inflight Window: %%
%%% %%
%%% |<----------------- Max Len ----------------->| %% 1. Inflight Window to store the messages delivered and awaiting for puback.
%%% ----------------------------------------------- %%
%%% IN -> | Messages Queue | Inflight Window | -> Out %% 2. Enqueue messages when the inflight window is full.
%%% ----------------------------------------------- %%
%%% |<--- Win Size --->| %% 3. If the queue is full, dropped qos0 messages if store_qos0 is true,
%%% %% otherwise dropped the oldest one.
%%% %%
%%% 1. Inflight Window to store the messages delivered and awaiting for puback. %% @end
%%% %%
%%% 2. Enqueue messages when the inflight window is full. %% @author Feng Lee <feng@emqtt.io>
%%%
%%% 3. If the queue is full, dropped qos0 messages if store_qos0 is true,
%%% otherwise dropped the oldest one.
%%%
%%% @end
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_mqueue). -module(emqttd_mqueue).
-include("emqttd.hrl"). -include("emqttd.hrl").

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd net utility functions. some functions copied from rabbitmq.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd net utility functions. some functions copied from rabbitmq.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_net). -module(emqttd_net).
-include_lib("kernel/include/inet.hrl"). -include_lib("kernel/include/inet.hrl").

View File

@ -1,36 +1,26 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd options handler.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd options handler.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_opts). -module(emqttd_opts).
-export([merge/2, g/2, g/3]). -export([merge/2, g/2, g/3]).
%%------------------------------------------------------------------------------
%% @doc Merge Options %% @doc Merge Options
%% @end
%%------------------------------------------------------------------------------
merge(Defaults, Options) -> merge(Defaults, Options) ->
lists:foldl( lists:foldl(
fun({Opt, Val}, Acc) -> fun({Opt, Val}, Acc) ->
@ -45,10 +35,7 @@ merge(Defaults, Options) ->
end end
end, Defaults, Options). end, Defaults, Options).
%%------------------------------------------------------------------------------
%% @doc Get option %% @doc Get option
%% @end
%%------------------------------------------------------------------------------
g(Key, Options) -> g(Key, Options) ->
proplists:get_value(Key, Options). proplists:get_value(Key, Options).

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc MQTT Packet Functions
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc MQTT Packet Functions
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_packet). -module(emqttd_packet).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -34,26 +27,17 @@
-export([format/1]). -export([format/1]).
%%------------------------------------------------------------------------------
%% @doc Protocol name of version %% @doc Protocol name of version
%% @end
%%------------------------------------------------------------------------------
-spec protocol_name(mqtt_vsn()) -> binary(). -spec protocol_name(mqtt_vsn()) -> binary().
protocol_name(Ver) when Ver =:= ?MQTT_PROTO_V31; Ver =:= ?MQTT_PROTO_V311-> protocol_name(Ver) when Ver =:= ?MQTT_PROTO_V31; Ver =:= ?MQTT_PROTO_V311->
proplists:get_value(Ver, ?PROTOCOL_NAMES). proplists:get_value(Ver, ?PROTOCOL_NAMES).
%%------------------------------------------------------------------------------
%% @doc Name of MQTT packet type %% @doc Name of MQTT packet type
%% @end
%%------------------------------------------------------------------------------
-spec type_name(mqtt_packet_type()) -> atom(). -spec type_name(mqtt_packet_type()) -> atom().
type_name(Type) when Type > ?RESERVED andalso Type =< ?DISCONNECT -> type_name(Type) when Type > ?RESERVED andalso Type =< ?DISCONNECT ->
lists:nth(Type, ?TYPE_NAMES). lists:nth(Type, ?TYPE_NAMES).
%%------------------------------------------------------------------------------
%% @doc Connack Name %% @doc Connack Name
%% @end
%%------------------------------------------------------------------------------
-spec connack_name(mqtt_connack()) -> atom(). -spec connack_name(mqtt_connack()) -> atom().
connack_name(?CONNACK_ACCEPT) -> 'CONNACK_ACCEPT'; connack_name(?CONNACK_ACCEPT) -> 'CONNACK_ACCEPT';
connack_name(?CONNACK_PROTO_VER) -> 'CONNACK_PROTO_VER'; connack_name(?CONNACK_PROTO_VER) -> 'CONNACK_PROTO_VER';
@ -62,10 +46,7 @@ connack_name(?CONNACK_SERVER) -> 'CONNACK_SERVER';
connack_name(?CONNACK_CREDENTIALS) -> 'CONNACK_CREDENTIALS'; connack_name(?CONNACK_CREDENTIALS) -> 'CONNACK_CREDENTIALS';
connack_name(?CONNACK_AUTH) -> 'CONNACK_AUTH'. connack_name(?CONNACK_AUTH) -> 'CONNACK_AUTH'.
%%------------------------------------------------------------------------------
%% @doc Format packet %% @doc Format packet
%% @end
%%------------------------------------------------------------------------------
-spec format(mqtt_packet()) -> iolist(). -spec format(mqtt_packet()) -> iolist().
format(#mqtt_packet{header = Header, variable = Variable, payload = Payload}) -> format(#mqtt_packet{header = Header, variable = Variable, payload = Payload}) ->
format_header(Header, format_variable(Variable, Payload)). format_header(Header, format_variable(Variable, Payload)).
@ -115,7 +96,7 @@ format_variable(#mqtt_packet_connack{ack_flags = AckFlags,
format_variable(#mqtt_packet_publish{topic_name = TopicName, format_variable(#mqtt_packet_publish{topic_name = TopicName,
packet_id = PacketId}) -> packet_id = PacketId}) ->
io_lib:format("TopicName=~s, PacketId=~p", [TopicName, PacketId]); io_lib:format("Topic=~s, PacketId=~p", [TopicName, PacketId]);
format_variable(#mqtt_packet_puback{packet_id = PacketId}) -> format_variable(#mqtt_packet_puback{packet_id = PacketId}) ->
io_lib:format("PacketId=~p", [PacketId]); io_lib:format("PacketId=~p", [PacketId]);

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc MQTT Packet Parser
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc MQTT Packet Parser
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_parser). -module(emqttd_parser).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -38,10 +31,7 @@
-type parser() :: fun( (binary()) -> any() ). -type parser() :: fun( (binary()) -> any() ).
%%------------------------------------------------------------------------------
%% @doc Initialize a parser %% @doc Initialize a parser
%% @end
%%------------------------------------------------------------------------------
-spec new(Opts :: [option()]) -> parser(). -spec new(Opts :: [option()]) -> parser().
new(Opts) -> new(Opts) ->
fun(Bin) -> parse(Bin, {none, limit(Opts)}) end. fun(Bin) -> parse(Bin, {none, limit(Opts)}) end.
@ -50,11 +40,9 @@ limit(Opts) ->
#mqtt_packet_limit{max_packet_size = #mqtt_packet_limit{max_packet_size =
proplists:get_value(max_packet_size, Opts, ?MAX_LEN)}. proplists:get_value(max_packet_size, Opts, ?MAX_LEN)}.
%%------------------------------------------------------------------------------
%% @doc Parse MQTT Packet %% @doc Parse MQTT Packet
%% @end -spec parse(binary(), {none, [option()]} | fun()) ->
%%------------------------------------------------------------------------------ {ok, mqtt_packet()} | {error, any()} | {more, fun()}.
-spec parse(binary(), {none, [option()]} | fun()) -> {ok, mqtt_packet()} | {error, any()} | {more, fun()}.
parse(<<>>, {none, Limit}) -> parse(<<>>, {none, Limit}) ->
{more, fun(Bin) -> parse(Bin, {none, Limit}) end}; {more, fun(Bin) -> parse(Bin, {none, Limit}) end};
parse(<<PacketType:4, Dup:1, QoS:2, Retain:1, Rest/binary>>, {none, Limit}) -> parse(<<PacketType:4, Dup:1, QoS:2, Retain:1, Rest/binary>>, {none, Limit}) ->

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd plugins.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd plugins.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_plugins). -module(emqttd_plugins).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -33,10 +26,7 @@
-export([list/0]). -export([list/0]).
%%------------------------------------------------------------------------------
%% @doc Load all plugins when the broker started. %% @doc Load all plugins when the broker started.
%% @end
%%------------------------------------------------------------------------------
-spec load() -> list() | {error, any()}. -spec load() -> list() | {error, any()}.
load() -> load() ->
case env(loaded_file) of case env(loaded_file) of
@ -65,10 +55,7 @@ load_plugins(Names, Persistent) ->
NeedToLoad = Names -- NotFound -- names(started_app), NeedToLoad = Names -- NotFound -- names(started_app),
[load_plugin(find_plugin(Name, Plugins), Persistent) || Name <- NeedToLoad]. [load_plugin(find_plugin(Name, Plugins), Persistent) || Name <- NeedToLoad].
%%------------------------------------------------------------------------------
%% @doc Unload all plugins before broker stopped. %% @doc Unload all plugins before broker stopped.
%% @end
%%------------------------------------------------------------------------------
-spec unload() -> list() | {error, any()}. -spec unload() -> list() | {error, any()}.
unload() -> unload() ->
case env(loaded_file) of case env(loaded_file) of
@ -82,10 +69,7 @@ unload() ->
stop_plugins(Names) -> stop_plugins(Names) ->
[stop_app(App) || App <- Names]. [stop_app(App) || App <- Names].
%%------------------------------------------------------------------------------
%% @doc List all available plugins %% @doc List all available plugins
%% @end
%%------------------------------------------------------------------------------
-spec list() -> [mqtt_plugin()]. -spec list() -> [mqtt_plugin()].
list() -> list() ->
case env(plugins_dir) of case env(plugins_dir) of
@ -119,10 +103,7 @@ plugin(PluginsDir, AppFile0) ->
Descr = proplists:get_value(description, Attrs, ""), Descr = proplists:get_value(description, Attrs, ""),
#mqtt_plugin{name = Name, version = Ver, config = AppsEnv1, descr = Descr}. #mqtt_plugin{name = Name, version = Ver, config = AppsEnv1, descr = Descr}.
%%------------------------------------------------------------------------------
%% @doc Load One Plugin %% @doc Load One Plugin
%% @end
%%------------------------------------------------------------------------------
-spec load(atom()) -> ok | {error, any()}. -spec load(atom()) -> ok | {error, any()}.
load(PluginName) when is_atom(PluginName) -> load(PluginName) when is_atom(PluginName) ->
case lists:member(PluginName, names(started_app)) of case lists:member(PluginName, names(started_app)) of
@ -182,10 +163,7 @@ find_plugin(Name) ->
find_plugin(Name, Plugins) -> find_plugin(Name, Plugins) ->
lists:keyfind(Name, 2, Plugins). lists:keyfind(Name, 2, Plugins).
%%------------------------------------------------------------------------------
%% @doc UnLoad One Plugin %% @doc UnLoad One Plugin
%% @end
%%------------------------------------------------------------------------------
-spec unload(atom()) -> ok | {error, any()}. -spec unload(atom()) -> ok | {error, any()}.
unload(PluginName) when is_atom(PluginName) -> unload(PluginName) when is_atom(PluginName) ->
case {lists:member(PluginName, names(started_app)), lists:member(PluginName, names(plugin))} of case {lists:member(PluginName, names(started_app)), lists:member(PluginName, names(plugin))} of
@ -217,9 +195,9 @@ stop_app(App) ->
lager:error("stop plugin ~p error: ~p", [App]), {error, Reason} lager:error("stop plugin ~p error: ~p", [App]), {error, Reason}
end. end.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
names(plugin) -> names(plugin) ->
names(list()); names(list());

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Common Pool Supervisor
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Common Pool Supervisor
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_pool_sup). -module(emqttd_pool_sup).
-behaviour(supervisor). -behaviour(supervisor).

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd pooler.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd pooler.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_pooler). -module(emqttd_pooler).
-behaviour(gen_server). -behaviour(gen_server).
@ -41,40 +34,30 @@
-record(state, {pool, id}). -record(state, {pool, id}).
%%------------------------------------------------------------------------------
%% @doc Start Pooler Supervisor. %% @doc Start Pooler Supervisor.
%% @end
%%------------------------------------------------------------------------------
start_link() -> start_link() ->
emqttd_pool_sup:start_link(pooler, random, {?MODULE, start_link, []}). emqttd_pool_sup:start_link(pooler, random, {?MODULE, start_link, []}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
-spec start_link(atom(), pos_integer()) -> {ok, pid()} | ignore | {error, any()}. -spec start_link(atom(), pos_integer()) -> {ok, pid()} | ignore | {error, any()}.
start_link(Pool, Id) -> start_link(Pool, Id) ->
gen_server:start_link({local, emqttd:reg_name(?MODULE, Id)}, ?MODULE, [Pool, Id], []). gen_server:start_link({local, emqttd:reg_name(?MODULE, Id)}, ?MODULE, [Pool, Id], []).
%%------------------------------------------------------------------------------
%% @doc Submit work to pooler %% @doc Submit work to pooler
%% @end submit(Fun) -> gen_server:call(worker(), {submit, Fun}, infinity).
%%------------------------------------------------------------------------------
submit(Fun) ->
gen_server:call(worker(), {submit, Fun}, infinity).
%%------------------------------------------------------------------------------
%% @doc Submit work to pooler asynchronously %% @doc Submit work to pooler asynchronously
%% @end
%%------------------------------------------------------------------------------
async_submit(Fun) -> async_submit(Fun) ->
gen_server:cast(worker(), {async_submit, Fun}). gen_server:cast(worker(), {async_submit, Fun}).
worker() -> worker() ->
gproc_pool:pick_worker(pooler). gproc_pool:pick_worker(pooler).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([Pool, Id]) -> init([Pool, Id]) ->
?GPROC_POOL(join, Pool, Id), ?GPROC_POOL(join, Pool, Id),
@ -105,9 +88,9 @@ terminate(_Reason, #state{pool = Pool, id = Id}) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
run({M, F, A}) -> run({M, F, A}) ->
erlang:apply(M, F, A); erlang:apply(M, F, A);

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd protocol.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd protocol.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_protocol). -module(emqttd_protocol).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -55,10 +48,7 @@
lager:Level([{client, State#proto_state.client_id}], "Client(~s@~s): " ++ Format, lager:Level([{client, State#proto_state.client_id}], "Client(~s@~s): " ++ Format,
[State#proto_state.client_id, esockd_net:format(State#proto_state.peername) | Args])). [State#proto_state.client_id, esockd_net:format(State#proto_state.peername) | Args])).
%%------------------------------------------------------------------------------
%% @doc Init protocol %% @doc Init protocol
%% @end
%%------------------------------------------------------------------------------
init(Peername, SendFun, Opts) -> init(Peername, SendFun, Opts) ->
MaxLen = emqttd_opts:g(max_clientid_len, Opts, ?MAX_CLIENTID_LEN), MaxLen = emqttd_opts:g(max_clientid_len, Opts, ?MAX_CLIENTID_LEN),
WsInitialHeaders = emqttd_opts:g(ws_initial_headers, Opts), WsInitialHeaders = emqttd_opts:g(ws_initial_headers, Opts),
@ -315,9 +305,10 @@ start_keepalive(0) -> ignore;
start_keepalive(Sec) when Sec > 0 -> start_keepalive(Sec) when Sec > 0 ->
self() ! {keepalive, start, round(Sec * 1.2)}. self() ! {keepalive, start, round(Sec * 1.2)}.
%%---------------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Validate Packets %% Validate Packets
%%---------------------------------------------------------------------------- %%--------------------------------------------------------------------
validate_connect(Connect = #mqtt_packet_connect{}, ProtoState) -> validate_connect(Connect = #mqtt_packet_connect{}, ProtoState) ->
case validate_protocol(Connect) of case validate_protocol(Connect) of
true -> true ->

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Core PubSub
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc PubSub
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_pubsub). -module(emqttd_pubsub).
-behaviour(gen_server2). -behaviour(gen_server2).
@ -60,9 +53,9 @@
-define(ROUTER, emqttd_router). -define(ROUTER, emqttd_router).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Mnesia callbacks %% Mnesia callbacks
%%%============================================================================= %%--------------------------------------------------------------------
mnesia(boot) -> mnesia(boot) ->
ok = create_table(topic, ram_copies), ok = create_table(topic, ram_copies),
if_subscription(fun(RamOrDisc) -> if_subscription(fun(RamOrDisc) ->
@ -115,9 +108,9 @@ cache_env(Key) ->
put({pubsub, Key}, Val), put({pubsub, Key}, Val),
Val. Val.
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%% @doc Start one pubsub server %% @doc Start one pubsub server
-spec start_link(Pool, Id, StatsFun, Opts) -> {ok, pid()} | ignore | {error, any()} when -spec start_link(Pool, Id, StatsFun, Opts) -> {ok, pid()} | ignore | {error, any()} when
@ -241,9 +234,9 @@ match(To) ->
%% ets:lookup for topic table will be replicated to all nodes. %% ets:lookup for topic table will be replicated to all nodes.
lists:append([ets:lookup(topic, Topic) || Topic <- MatchedTopics]). lists:append([ets:lookup(topic, Topic) || Topic <- MatchedTopics]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([Pool, Id, StatsFun, _Opts]) -> init([Pool, Id, StatsFun, _Opts]) ->
?GPROC_POOL(join, Pool, Id), ?GPROC_POOL(join, Pool, Id),
@ -332,9 +325,9 @@ terminate(_Reason, #state{pool = Pool, id = Id}) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
add_topics(Records) -> add_topics(Records) ->
lists:foreach(fun add_topic/1, Records). lists:foreach(fun add_topic/1, Records).
@ -410,9 +403,9 @@ try_monitor(SubPid) ->
false -> erlang:monitor(process, SubPid) false -> erlang:monitor(process, SubPid)
end. end.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Trace Functions %% Trace Functions
%%%============================================================================= %%--------------------------------------------------------------------
trace(publish, From, _Msg) when is_atom(From) -> trace(publish, From, _Msg) when is_atom(From) ->
%% Dont' trace '$SYS' publish %% Dont' trace '$SYS' publish

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc PubSub Helper. %%% @doc PubSub Helper.
%%%
%%% @author Feng Lee <feng@emqtt.io> %%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_pubsub_helper). -module(emqttd_pubsub_helper).
-behaviour(gen_server). -behaviour(gen_server).
@ -47,9 +40,9 @@
start_link(StatsFun) -> start_link(StatsFun) ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [StatsFun], []). gen_server:start_link({local, ?SERVER}, ?MODULE, [StatsFun], []).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([StatsFun]) -> init([StatsFun]) ->
mnesia:subscribe(system), mnesia:subscribe(system),

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc PubSub Supervisor.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc PubSub Supervisor.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_pubsub_sup). -module(emqttd_pubsub_sup).
-behaviour(supervisor). -behaviour(supervisor).

View File

@ -1,32 +1,22 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% TODO: should match topic tree
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @doc MQTT retained message storage.
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% @author Feng Lee <feng@emqtt.io>
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc MQTT retained message storage.
%%%
%%% TODO: should match topic tree
%%%
%%% @end
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_retainer). -module(emqttd_retainer).
-behaviour(gen_server). -behaviour(gen_server).
@ -57,9 +47,9 @@
-record(state, {stats_fun, expired_after, stats_timer, expire_timer}). -record(state, {stats_fun, expired_after, stats_timer, expire_timer}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Mnesia callbacks %% Mnesia callbacks
%%%============================================================================= %%--------------------------------------------------------------------
mnesia(boot) -> mnesia(boot) ->
ok = emqttd_mnesia:create_table(retained, [ ok = emqttd_mnesia:create_table(retained, [
@ -70,22 +60,16 @@ mnesia(boot) ->
mnesia(copy) -> mnesia(copy) ->
ok = emqttd_mnesia:copy_table(retained). ok = emqttd_mnesia:copy_table(retained).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Start a retained server %% @doc Start a retained server
%% @end
%%------------------------------------------------------------------------------
-spec start_link() -> {ok, pid()} | ignore | {error, any()}. -spec start_link() -> {ok, pid()} | ignore | {error, any()}.
start_link() -> start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
%%%-----------------------------------------------------------------------------
%% @doc Retain message %% @doc Retain message
%% @end
%%%-----------------------------------------------------------------------------
-spec retain(mqtt_message()) -> ok | ignore. -spec retain(mqtt_message()) -> ok | ignore.
retain(#mqtt_message{retain = false}) -> ignore; retain(#mqtt_message{retain = false}) -> ignore;
@ -121,10 +105,7 @@ env(Key) ->
Val Val
end. end.
%%%-----------------------------------------------------------------------------
%% @doc Deliver retained messages to subscribed client %% @doc Deliver retained messages to subscribed client
%% @end
%%%-----------------------------------------------------------------------------
-spec dispatch(Topic, CPid) -> any() when -spec dispatch(Topic, CPid) -> any() when
Topic :: binary(), Topic :: binary(),
CPid :: pid(). CPid :: pid().
@ -144,9 +125,9 @@ dispatch(Topic, CPid) when is_binary(Topic) ->
end, end,
lists:foreach(fun(Msg) -> CPid ! {dispatch, Topic, Msg} end, lists:reverse(Msgs)). lists:foreach(fun(Msg) -> CPid ! {dispatch, Topic, Msg} end, lists:reverse(Msgs)).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([]) -> init([]) ->
StatsFun = emqttd_stats:statsfun('retained/count', 'retained/max'), StatsFun = emqttd_stats:statsfun('retained/count', 'retained/max'),
@ -187,9 +168,9 @@ terminate(_Reason, _State = #state{stats_timer = TRef1, expire_timer = TRef2}) -
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
expire(Time) -> expire(Time) ->
mnesia:async_dirty( mnesia:async_dirty(

View File

@ -1,29 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Message Router on local node.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
%% @doc Message Router on local node.
%% @author Feng Lee <feng@emqtt.io>
-module(emqttd_router). -module(emqttd_router).
-behaviour(gen_server2). -behaviour(gen_server2).

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc MQTT Packet Serializer
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc MQTT Packet Serializer
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_serializer). -module(emqttd_serializer).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -32,10 +25,7 @@
%% API %% API
-export([serialize/1]). -export([serialize/1]).
%%------------------------------------------------------------------------------
%% @doc Serialise MQTT Packet %% @doc Serialise MQTT Packet
%% @end
%%------------------------------------------------------------------------------
-spec serialize(mqtt_packet()) -> binary(). -spec serialize(mqtt_packet()) -> binary().
serialize(#mqtt_packet{header = Header = #mqtt_packet_header{type = Type}, serialize(#mqtt_packet{header = Header = #mqtt_packet_header{type = Type},
variable = Variable, variable = Variable,

View File

@ -1,49 +1,43 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Session for persistent MQTT client.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %%
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% Session State in the broker consists of:
%%% SOFTWARE. %%
%%%----------------------------------------------------------------------------- %% 1. The Clients subscriptions.
%%% @doc Session for persistent MQTT client. %%
%%% %% 2. inflight qos1/2 messages sent to the client but unacked, QoS 1 and QoS 2
%%% Session State in the broker consists of: %% messages which have been sent to the Client, but have not been completely
%%% %% acknowledged.
%%% 1. The Clients subscriptions. %%
%%% %% 3. inflight qos2 messages received from client and waiting for pubrel. QoS 2
%%% 2. inflight qos1/2 messages sent to the client but unacked, QoS 1 and QoS 2 %% messages which have been received from the Client, but have not been
%%% messages which have been sent to the Client, but have not been completely %% completely acknowledged.
%%% acknowledged. %%
%%% %% 4. all qos1, qos2 messages published to when client is disconnected.
%%% 3. inflight qos2 messages received from client and waiting for pubrel. QoS 2 %% QoS 1 and QoS 2 messages pending transmission to the Client.
%%% messages which have been received from the Client, but have not been %%
%%% completely acknowledged. %% 5. Optionally, QoS 0 messages pending transmission to the Client.
%%% %%
%%% 4. all qos1, qos2 messages published to when client is disconnected. %% State of Message: newcome, inflight, pending
%%% QoS 1 and QoS 2 messages pending transmission to the Client. %%
%%% %% @end
%%% 5. Optionally, QoS 0 messages pending transmission to the Client. %%
%%% %% @author Feng Lee <feng@emqtt.io>
%%% State of Message: newcome, inflight, pending
%%%
%%% @end
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_session). -module(emqttd_session).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -140,41 +134,26 @@
lager:Level([{client, State#session.client_id}], lager:Level([{client, State#session.client_id}],
"Session(~s): " ++ Format, [State#session.client_id | Args])). "Session(~s): " ++ Format, [State#session.client_id | Args])).
%%------------------------------------------------------------------------------
%% @doc Start a session. %% @doc Start a session.
%% @end
%%------------------------------------------------------------------------------
-spec start_link(boolean(), mqtt_client_id(), pid()) -> {ok, pid()} | {error, any()}. -spec start_link(boolean(), mqtt_client_id(), pid()) -> {ok, pid()} | {error, any()}.
start_link(CleanSess, ClientId, ClientPid) -> start_link(CleanSess, ClientId, ClientPid) ->
gen_server2:start_link(?MODULE, [CleanSess, ClientId, ClientPid], []). gen_server2:start_link(?MODULE, [CleanSess, ClientId, ClientPid], []).
%%------------------------------------------------------------------------------
%% @doc Resume a session. %% @doc Resume a session.
%% @end
%%------------------------------------------------------------------------------
-spec resume(pid(), mqtt_client_id(), pid()) -> ok. -spec resume(pid(), mqtt_client_id(), pid()) -> ok.
resume(SessPid, ClientId, ClientPid) -> resume(SessPid, ClientId, ClientPid) ->
gen_server2:cast(SessPid, {resume, ClientId, ClientPid}). gen_server2:cast(SessPid, {resume, ClientId, ClientPid}).
%%------------------------------------------------------------------------------
%% @doc Session Info. %% @doc Session Info.
%% @end
%%------------------------------------------------------------------------------
info(SessPid) -> info(SessPid) ->
gen_server2:call(SessPid, info). gen_server2:call(SessPid, info).
%%------------------------------------------------------------------------------
%% @doc Destroy a session. %% @doc Destroy a session.
%% @end
%%------------------------------------------------------------------------------
-spec destroy(pid(), mqtt_client_id()) -> ok. -spec destroy(pid(), mqtt_client_id()) -> ok.
destroy(SessPid, ClientId) -> destroy(SessPid, ClientId) ->
gen_server2:cast(SessPid, {destroy, ClientId}). gen_server2:cast(SessPid, {destroy, ClientId}).
%%------------------------------------------------------------------------------
%% @doc Subscribe Topics %% @doc Subscribe Topics
%% @end
%%------------------------------------------------------------------------------
-spec subscribe(pid(), [{binary(), mqtt_qos()}]) -> ok. -spec subscribe(pid(), [{binary(), mqtt_qos()}]) -> ok.
subscribe(SessPid, TopicTable) -> subscribe(SessPid, TopicTable) ->
gen_server2:cast(SessPid, {subscribe, TopicTable, fun(_) -> ok end}). gen_server2:cast(SessPid, {subscribe, TopicTable, fun(_) -> ok end}).
@ -187,10 +166,7 @@ subscribe(SessPid, PacketId, TopicTable) ->
end, end,
gen_server2:cast(SessPid, {subscribe, TopicTable, AckFun}). gen_server2:cast(SessPid, {subscribe, TopicTable, AckFun}).
%%------------------------------------------------------------------------------
%% @doc Publish message %% @doc Publish message
%% @end
%%------------------------------------------------------------------------------
-spec publish(pid(), mqtt_message()) -> ok | {error, any()}. -spec publish(pid(), mqtt_message()) -> ok | {error, any()}.
publish(_SessPid, Msg = #mqtt_message{qos = ?QOS_0}) -> publish(_SessPid, Msg = #mqtt_message{qos = ?QOS_0}) ->
%% publish qos0 directly %% publish qos0 directly
@ -204,10 +180,7 @@ publish(SessPid, Msg = #mqtt_message{qos = ?QOS_2}) ->
%% publish qos2 by session %% publish qos2 by session
gen_server2:call(SessPid, {publish, Msg}, ?PUBSUB_TIMEOUT). gen_server2:call(SessPid, {publish, Msg}, ?PUBSUB_TIMEOUT).
%%------------------------------------------------------------------------------
%% @doc PubAck message %% @doc PubAck message
%% @end
%%------------------------------------------------------------------------------
-spec puback(pid(), mqtt_packet_id()) -> ok. -spec puback(pid(), mqtt_packet_id()) -> ok.
puback(SessPid, PktId) -> puback(SessPid, PktId) ->
gen_server2:cast(SessPid, {puback, PktId}). gen_server2:cast(SessPid, {puback, PktId}).
@ -224,17 +197,14 @@ pubrel(SessPid, PktId) ->
pubcomp(SessPid, PktId) -> pubcomp(SessPid, PktId) ->
gen_server2:cast(SessPid, {pubcomp, PktId}). gen_server2:cast(SessPid, {pubcomp, PktId}).
%%------------------------------------------------------------------------------
%% @doc Unsubscribe Topics %% @doc Unsubscribe Topics
%% @end
%%------------------------------------------------------------------------------
-spec unsubscribe(pid(), [binary()]) -> ok. -spec unsubscribe(pid(), [binary()]) -> ok.
unsubscribe(SessPid, Topics) -> unsubscribe(SessPid, Topics) ->
gen_server2:cast(SessPid, {unsubscribe, Topics}). gen_server2:cast(SessPid, {unsubscribe, Topics}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([CleanSess, ClientId, ClientPid]) -> init([CleanSess, ClientId, ClientPid]) ->
process_flag(trap_exit, true), process_flag(trap_exit, true),
@ -564,13 +534,9 @@ terminate(_Reason, #session{clean_sess = CleanSess, client_id = ClientId}) ->
code_change(_OldVsn, Session, _Extra) -> code_change(_OldVsn, Session, _Extra) ->
{ok, Session}. {ok, Session}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions
%%%=============================================================================
%%------------------------------------------------------------------------------
%% Kick old client out %% Kick old client out
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
kick(_ClientId, undefined, _Pid) -> kick(_ClientId, undefined, _Pid) ->
ignore; ignore;
kick(_ClientId, Pid, Pid) -> kick(_ClientId, Pid, Pid) ->
@ -581,9 +547,9 @@ kick(ClientId, OldPid, Pid) ->
%% Clean noproc %% Clean noproc
receive {'EXIT', OldPid, _} -> ok after 0 -> ok end. receive {'EXIT', OldPid, _} -> ok after 0 -> ok end.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% Dispatch Messages %% Dispatch Messages
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% Queue message if client disconnected %% Queue message if client disconnected
dispatch(Msg, Session = #session{client_pid = undefined, message_queue = Q}) -> dispatch(Msg, Session = #session{client_pid = undefined, message_queue = Q}) ->
@ -613,9 +579,9 @@ tune_qos(Topic, Msg = #mqtt_message{qos = PubQos}, Subscriptions) ->
Msg Msg
end. end.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% Check inflight and awaiting_rel %% Check inflight and awaiting_rel
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
check_inflight(#session{max_inflight = 0}) -> check_inflight(#session{max_inflight = 0}) ->
true; true;
@ -628,9 +594,9 @@ check_awaiting_rel(#session{awaiting_rel = AwaitingRel,
max_awaiting_rel = MaxLen}) -> max_awaiting_rel = MaxLen}) ->
maps:size(AwaitingRel) < MaxLen. maps:size(AwaitingRel) < MaxLen.
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% Dequeue and Deliver %% Dequeue and Deliver
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
dequeue(Session = #session{client_pid = undefined}) -> dequeue(Session = #session{client_pid = undefined}) ->
%% do nothing if client is disconnected %% do nothing if client is disconnected
@ -670,7 +636,7 @@ redeliver(Msg = #mqtt_message{qos = QoS}, Session = #session{client_pid = Client
ClientPid ! {deliver, Msg#mqtt_message{dup = true}}, ClientPid ! {deliver, Msg#mqtt_message{dup = true}},
await(Msg, Session). await(Msg, Session).
%%------------------------------------------------------------------------------ %%--------------------------------------------------------------------
%% Awaiting ack for qos1, qos2 message %% Awaiting ack for qos1, qos2 message
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
await(#mqtt_message{pktid = PktId}, Session = #session{awaiting_ack = Awaiting, await(#mqtt_message{pktid = PktId}, Session = #session{awaiting_ack = Awaiting,

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd session supervisor.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd session supervisor.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_session_sup). -module(emqttd_session_sup).
-behavior(supervisor). -behavior(supervisor).
@ -31,29 +24,22 @@
-export([init/1]). -export([init/1]).
%%------------------------------------------------------------------------------
%% @doc Start session supervisor %% @doc Start session supervisor
%% @end
%%------------------------------------------------------------------------------
-spec start_link() -> {ok, pid()}. -spec start_link() -> {ok, pid()}.
start_link() -> start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []). supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%%------------------------------------------------------------------------------
%% @doc Start a session %% @doc Start a session
%% @end
%%------------------------------------------------------------------------------
-spec start_session(boolean(), binary(), pid()) -> {ok, pid()}. -spec start_session(boolean(), binary(), pid()) -> {ok, pid()}.
start_session(CleanSess, ClientId, ClientPid) -> start_session(CleanSess, ClientId, ClientPid) ->
supervisor:start_child(?MODULE, [CleanSess, ClientId, ClientPid]). supervisor:start_child(?MODULE, [CleanSess, ClientId, ClientPid]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Supervisor callbacks %% Supervisor callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([]) -> init([]) ->
{ok, {{simple_one_for_one, 10, 10}, {ok, {{simple_one_for_one, 10, 10},
[{session, {emqttd_session, start_link, []}, [{session, {emqttd_session, start_link, []},
temporary, 10000, worker, [emqttd_session]}]}}. temporary, 10000, worker, [emqttd_session]}]}}.

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Session Manager
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Session Manager
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_sm). -module(emqttd_sm).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -60,9 +53,9 @@
-define(LOG(Level, Format, Args, Session), -define(LOG(Level, Format, Args, Session),
lager:Level("SM(~s): " ++ Format, [Session#mqtt_session.client_id | Args])). lager:Level("SM(~s): " ++ Format, [Session#mqtt_session.client_id | Args])).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Mnesia callbacks %% Mnesia callbacks
%%%============================================================================= %%--------------------------------------------------------------------
mnesia(boot) -> mnesia(boot) ->
%% Global Session Table %% Global Session Table
@ -75,31 +68,22 @@ mnesia(boot) ->
mnesia(copy) -> mnesia(copy) ->
ok = emqttd_mnesia:copy_table(session). ok = emqttd_mnesia:copy_table(session).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Start a session manager %% @doc Start a session manager
%% @end
%%------------------------------------------------------------------------------
-spec start_link(atom(), pos_integer()) -> {ok, pid()} | ignore | {error, any()}. -spec start_link(atom(), pos_integer()) -> {ok, pid()} | ignore | {error, any()}.
start_link(Pool, Id) -> start_link(Pool, Id) ->
gen_server2:start_link({local, emqttd:reg_name(?MODULE, Id)}, ?MODULE, [Pool, Id], []). gen_server2:start_link({local, emqttd:reg_name(?MODULE, Id)}, ?MODULE, [Pool, Id], []).
%%------------------------------------------------------------------------------
%% @doc Start a session %% @doc Start a session
%% @end
%%------------------------------------------------------------------------------
-spec start_session(CleanSess :: boolean(), binary()) -> {ok, pid(), boolean()} | {error, any()}. -spec start_session(CleanSess :: boolean(), binary()) -> {ok, pid(), boolean()} | {error, any()}.
start_session(CleanSess, ClientId) -> start_session(CleanSess, ClientId) ->
SM = gproc_pool:pick_worker(?POOL, ClientId), SM = gproc_pool:pick_worker(?POOL, ClientId),
call(SM, {start_session, {CleanSess, ClientId, self()}}). call(SM, {start_session, {CleanSess, ClientId, self()}}).
%%------------------------------------------------------------------------------
%% @doc Lookup a Session %% @doc Lookup a Session
%% @end
%%------------------------------------------------------------------------------
-spec lookup_session(binary()) -> mqtt_session() | undefined. -spec lookup_session(binary()) -> mqtt_session() | undefined.
lookup_session(ClientId) -> lookup_session(ClientId) ->
case mnesia:dirty_read(session, ClientId) of case mnesia:dirty_read(session, ClientId) of
@ -107,10 +91,7 @@ lookup_session(ClientId) ->
[] -> undefined [] -> undefined
end. end.
%%------------------------------------------------------------------------------
%% @doc Register a session with info. %% @doc Register a session with info.
%% @end
%%------------------------------------------------------------------------------
-spec register_session(CleanSess, ClientId, Info) -> ok when -spec register_session(CleanSess, ClientId, Info) -> ok when
CleanSess :: boolean(), CleanSess :: boolean(),
ClientId :: binary(), ClientId :: binary(),
@ -118,10 +99,7 @@ lookup_session(ClientId) ->
register_session(CleanSess, ClientId, Info) -> register_session(CleanSess, ClientId, Info) ->
ets:insert(sesstab(CleanSess), {{ClientId, self()}, Info}). ets:insert(sesstab(CleanSess), {{ClientId, self()}, Info}).
%%------------------------------------------------------------------------------
%% @doc Unregister a session. %% @doc Unregister a session.
%% @end
%%------------------------------------------------------------------------------
-spec unregister_session(CleanSess, ClientId) -> ok when -spec unregister_session(CleanSess, ClientId) -> ok when
CleanSess :: boolean(), CleanSess :: boolean(),
ClientId :: binary(). ClientId :: binary().
@ -134,9 +112,9 @@ sesstab(false) -> mqtt_persistent_session.
call(SM, Req) -> call(SM, Req) ->
gen_server2:call(SM, Req, ?TIMEOUT). %%infinity). gen_server2:call(SM, Req, ?TIMEOUT). %%infinity).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([Pool, Id]) -> init([Pool, Id]) ->
?GPROC_POOL(join, Pool, Id), ?GPROC_POOL(join, Pool, Id),
@ -213,9 +191,9 @@ terminate(_Reason, #state{pool = Pool, id = Id}) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
%% Create Session Locally %% Create Session Locally
create_session({CleanSess, ClientId, ClientPid}, State) -> create_session({CleanSess, ClientId, ClientPid}, State) ->

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Session Helper.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Session Helper.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_sm_helper). -module(emqttd_sm_helper).
-behaviour(gen_server). -behaviour(gen_server).
@ -42,10 +35,7 @@
-record(state, {stats_fun, tick_tref}). -record(state, {stats_fun, tick_tref}).
%%------------------------------------------------------------------------------
%% @doc Start a session helper %% @doc Start a session helper
%% @end
%%------------------------------------------------------------------------------
-spec start_link(fun()) -> {ok, pid()} | ignore | {error, any()}. -spec start_link(fun()) -> {ok, pid()} | ignore | {error, any()}.
start_link(StatsFun) -> start_link(StatsFun) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [StatsFun], []). gen_server:start_link({local, ?MODULE}, ?MODULE, [StatsFun], []).
@ -89,9 +79,9 @@ terminate(_Reason, _State = #state{tick_tref = TRef}) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
setstats(State = #state{stats_fun = StatsFun}) -> setstats(State = #state{stats_fun = StatsFun}) ->
StatsFun(ets:info(mqtt_persistent_session, size)), State. StatsFun(ets:info(mqtt_persistent_session, size)), State.

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Session Manager Supervisor.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Session Manager Supervisor.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_sm_sup). -module(emqttd_sm_sup).
-behaviour(supervisor). -behaviour(supervisor).

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd statistics
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd statistics
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_stats). -module(emqttd_stats).
-include("emqttd.hrl"). -include("emqttd.hrl").
@ -76,14 +69,11 @@
'retained/max' 'retained/max'
]). ]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc Start stats server %% @doc Start stats server
%% @end
%%------------------------------------------------------------------------------
-spec start_link() -> {ok, pid()} | ignore | {error, term()}. -spec start_link() -> {ok, pid()} | ignore | {error, term()}.
start_link() -> start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
@ -91,10 +81,7 @@ start_link() ->
stop() -> stop() ->
gen_server:call(?SERVER, stop). gen_server:call(?SERVER, stop).
%%------------------------------------------------------------------------------
%% @doc Generate stats fun %% @doc Generate stats fun
%% @end
%%------------------------------------------------------------------------------
-spec statsfun(Stat :: atom()) -> fun(). -spec statsfun(Stat :: atom()) -> fun().
statsfun(Stat) -> statsfun(Stat) ->
fun(Val) -> setstat(Stat, Val) end. fun(Val) -> setstat(Stat, Val) end.
@ -103,18 +90,12 @@ statsfun(Stat) ->
statsfun(Stat, MaxStat) -> statsfun(Stat, MaxStat) ->
fun(Val) -> setstats(Stat, MaxStat, Val) end. fun(Val) -> setstats(Stat, MaxStat, Val) end.
%%------------------------------------------------------------------------------
%% @doc Get broker statistics %% @doc Get broker statistics
%% @end
%%------------------------------------------------------------------------------
-spec getstats() -> [{atom(), non_neg_integer()}]. -spec getstats() -> [{atom(), non_neg_integer()}].
getstats() -> getstats() ->
lists:sort(ets:tab2list(?STATS_TAB)). lists:sort(ets:tab2list(?STATS_TAB)).
%%------------------------------------------------------------------------------
%% @doc Get stats by name %% @doc Get stats by name
%% @end
%%------------------------------------------------------------------------------
-spec getstat(atom()) -> non_neg_integer() | undefined. -spec getstat(atom()) -> non_neg_integer() | undefined.
getstat(Name) -> getstat(Name) ->
case ets:lookup(?STATS_TAB, Name) of case ets:lookup(?STATS_TAB, Name) of
@ -122,25 +103,19 @@ getstat(Name) ->
[] -> undefined [] -> undefined
end. end.
%%------------------------------------------------------------------------------
%% @doc Set broker stats %% @doc Set broker stats
%% @end
%%------------------------------------------------------------------------------
-spec setstat(Stat :: atom(), Val :: pos_integer()) -> boolean(). -spec setstat(Stat :: atom(), Val :: pos_integer()) -> boolean().
setstat(Stat, Val) -> setstat(Stat, Val) ->
ets:update_element(?STATS_TAB, Stat, {2, Val}). ets:update_element(?STATS_TAB, Stat, {2, Val}).
%%------------------------------------------------------------------------------
%% @doc Set stats with max %% @doc Set stats with max
%% @end
%%------------------------------------------------------------------------------
-spec setstats(Stat :: atom(), MaxStat :: atom(), Val :: pos_integer()) -> boolean(). -spec setstats(Stat :: atom(), MaxStat :: atom(), Val :: pos_integer()) -> boolean().
setstats(Stat, MaxStat, Val) -> setstats(Stat, MaxStat, Val) ->
gen_server:cast(?MODULE, {setstats, Stat, MaxStat, Val}). gen_server:cast(?MODULE, {setstats, Stat, MaxStat, Val}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([]) -> init([]) ->
emqttd:seed_now(), emqttd:seed_now(),
@ -186,9 +161,10 @@ terminate(_Reason, #state{tick_tref = TRef}) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
publish(Stat, Val) -> publish(Stat, Val) ->
Msg = emqttd_message:make(stats, stats_topic(Stat), Msg = emqttd_message:make(stats, stats_topic(Stat),
emqttd_util:integer_to_binary(Val)), emqttd_util:integer_to_binary(Val)),

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd top supervisor.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd top supervisor.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_sup). -module(emqttd_sup).
-behaviour(supervisor). -behaviour(supervisor).
@ -39,9 +32,9 @@
-define(CHILD(Mod, Type), {Mod, {Mod, start_link, []}, -define(CHILD(Mod, Type), {Mod, {Mod, start_link, []},
permanent, 5000, Type, [Mod]}). permanent, 5000, Type, [Mod]}).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
start_link() -> start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []). supervisor:start_link({local, ?MODULE}, ?MODULE, []).
@ -56,9 +49,9 @@ start_child(ChildSpec) when is_tuple(ChildSpec) ->
start_child(Mod, Type) when is_atom(Mod) and is_atom(Type) -> start_child(Mod, Type) when is_atom(Mod) and is_atom(Type) ->
supervisor:start_child(?MODULE, ?CHILD(Mod, Type)). supervisor:start_child(?MODULE, ?CHILD(Mod, Type)).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Supervisor callbacks %% Supervisor callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([]) -> init([]) ->
{ok, {{one_for_all, 10, 3600}, []}}. {ok, {{one_for_all, 10, 3600}, []}}.

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc VM System Monitor
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc VM System Monitor
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_sysmon). -module(emqttd_sysmon).
-behavior(gen_server). -behavior(gen_server).
@ -44,18 +37,15 @@
-define(LOG(Msg, ProcInfo, PortInfo), -define(LOG(Msg, ProcInfo, PortInfo),
lager:warning([{sysmon, true}], "~s~n~p~n~p", [WarnMsg, ProcInfo, PortInfo])). lager:warning([{sysmon, true}], "~s~n~p~n~p", [WarnMsg, ProcInfo, PortInfo])).
%%------------------------------------------------------------------------------
%% @doc Start system monitor %% @doc Start system monitor
%% @end
%%------------------------------------------------------------------------------
-spec start_link(Opts :: list(tuple())) -> -spec start_link(Opts :: list(tuple())) ->
{ok, pid()} | ignore | {error, term()}. {ok, pid()} | ignore | {error, term()}.
start_link(Opts) -> start_link(Opts) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [Opts], []). gen_server:start_link({local, ?MODULE}, ?MODULE, [Opts], []).
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([Opts]) -> init([Opts]) ->
erlang:system_monitor(self(), parse_opt(Opts)), erlang:system_monitor(self(), parse_opt(Opts)),

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd sysmon supervisor.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd sysmon supervisor.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_sysmon_sup). -module(emqttd_sysmon_sup).
-behaviour(supervisor). -behaviour(supervisor).

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc MQTT Topic Functions
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc MQTT Topic Functions
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_topic). -module(emqttd_topic).
-import(lists, [reverse/1]). -import(lists, [reverse/1]).

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Trace MQTT packets/messages by ClientID or Topic.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc Trace MQTT packets/messages by ClientID or Topic.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_trace). -module(emqttd_trace).
-behaviour(gen_server). -behaviour(gen_server).
@ -44,17 +37,15 @@
-define(TRACE_OPTIONS, [{formatter_config, [time, " [",severity,"] ", message, "\n"]}]). -define(TRACE_OPTIONS, [{formatter_config, [time, " [",severity,"] ", message, "\n"]}]).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
-spec start_link() -> {ok, pid()}. -spec start_link() -> {ok, pid()}.
start_link() -> start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
%%------------------------------------------------------------------------------
%% @doc Start to trace client or topic. %% @doc Start to trace client or topic.
%% @end
%%------------------------------------------------------------------------------
-spec start_trace(trace_who(), string()) -> ok | {error, any()}. -spec start_trace(trace_who(), string()) -> ok | {error, any()}.
start_trace({client, ClientId}, LogFile) -> start_trace({client, ClientId}, LogFile) ->
start_trace({start_trace, {client, ClientId}, LogFile}); start_trace({start_trace, {client, ClientId}, LogFile});
@ -62,26 +53,22 @@ start_trace({client, ClientId}, LogFile) ->
start_trace({topic, Topic}, LogFile) -> start_trace({topic, Topic}, LogFile) ->
start_trace({start_trace, {topic, Topic}, LogFile}). start_trace({start_trace, {topic, Topic}, LogFile}).
start_trace(Req) -> start_trace(Req) -> gen_server:call(?MODULE, Req, infinity).
gen_server:call(?MODULE, Req, infinity).
%%------------------------------------------------------------------------------
%% @doc Stop tracing client or topic. %% @doc Stop tracing client or topic.
%% @end
%%------------------------------------------------------------------------------
-spec stop_trace(trace_who()) -> ok | {error, any()}. -spec stop_trace(trace_who()) -> ok | {error, any()}.
stop_trace({client, ClientId}) -> stop_trace({client, ClientId}) ->
gen_server:call(?MODULE, {stop_trace, {client, ClientId}}); gen_server:call(?MODULE, {stop_trace, {client, ClientId}});
stop_trace({topic, Topic}) -> stop_trace({topic, Topic}) ->
gen_server:call(?MODULE, {stop_trace, {topic, Topic}}). gen_server:call(?MODULE, {stop_trace, {topic, Topic}}).
%%------------------------------------------------------------------------------
%% @doc Lookup all traces. %% @doc Lookup all traces.
%% @end
%%------------------------------------------------------------------------------
-spec all_traces() -> [{Who :: trace_who(), LogFile :: string()}]. -spec all_traces() -> [{Who :: trace_who(), LogFile :: string()}].
all_traces() -> all_traces() -> gen_server:call(?MODULE, all_traces).
gen_server:call(?MODULE, all_traces).
%%--------------------------------------------------------------------
%% gen_server callbacks
%%--------------------------------------------------------------------
init([]) -> init([]) ->
{ok, #state{level = info, traces = #{}}}. {ok, #state{level = info, traces = #{}}}.

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd trace supervisor.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd trace supervisor.
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_trace_sup). -module(emqttd_trace_sup).
-behaviour(supervisor). -behaviour(supervisor).

View File

@ -1,33 +1,25 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE %% @doc MQTT Topic Trie.
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %%
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% [Trie](http://en.wikipedia.org/wiki/Trie)
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %%
%%% SOFTWARE. %% @end
%%%----------------------------------------------------------------------------- %%
%%% @doc %% @author Feng Lee <feng@emqtt.io>
%%% MQTT Topic Trie.
%%%
%%% [Trie](http://en.wikipedia.org/wiki/Trie)
%%%
%%% @end
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_trie). -module(emqttd_trie).
%% Mnesia Callbacks %% Mnesia Callbacks
@ -57,14 +49,11 @@
node_id :: node_id() node_id :: node_id()
}). }).
%%%============================================================================= %%--------------------------------------------------------------------
%%% Mnesia Callbacks %% Mnesia Callbacks
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------ %% @doc Create Trie Tables.
%% @doc Create Trie Tables
%% @end
%%------------------------------------------------------------------------------
-spec mnesia(boot | copy) -> ok. -spec mnesia(boot | copy) -> ok.
mnesia(boot) -> mnesia(boot) ->
%% Trie Table %% Trie Table
@ -78,24 +67,18 @@ mnesia(boot) ->
{record_name, trie_node}, {record_name, trie_node},
{attributes, record_info(fields, trie_node)}]); {attributes, record_info(fields, trie_node)}]);
%%------------------------------------------------------------------------------ %% @doc Replicate trie tables.
%% @doc Replicate trie tables
%% @end
%%------------------------------------------------------------------------------
mnesia(copy) -> mnesia(copy) ->
%% Copy Trie Table %% Copy Trie Table
ok = emqttd_mnesia:copy_table(trie), ok = emqttd_mnesia:copy_table(trie),
%% Copy Trie Node Table %% Copy Trie Node Table
ok = emqttd_mnesia:copy_table(trie_node). ok = emqttd_mnesia:copy_table(trie_node).
%%%============================================================================= %%--------------------------------------------------------------------
%%% API %% API
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------ %% @doc Insert topic to trie tree.
%% @doc Insert topic to trie tree
%% @end
%%------------------------------------------------------------------------------
-spec insert(Topic :: binary()) -> ok. -spec insert(Topic :: binary()) -> ok.
insert(Topic) when is_binary(Topic) -> insert(Topic) when is_binary(Topic) ->
case mnesia:read(trie_node, Topic) of case mnesia:read(trie_node, Topic) of
@ -110,19 +93,13 @@ insert(Topic) when is_binary(Topic) ->
mnesia:write(#trie_node{node_id=Topic, topic=Topic}) mnesia:write(#trie_node{node_id=Topic, topic=Topic})
end. end.
%%------------------------------------------------------------------------------
%% @doc Find trie nodes that match topic %% @doc Find trie nodes that match topic
%% @end
%%------------------------------------------------------------------------------
-spec match(Topic :: binary()) -> list(MatchedTopic :: binary()). -spec match(Topic :: binary()) -> list(MatchedTopic :: binary()).
match(Topic) when is_binary(Topic) -> match(Topic) when is_binary(Topic) ->
TrieNodes = match_node(root, emqttd_topic:words(Topic)), TrieNodes = match_node(root, emqttd_topic:words(Topic)),
[Name || #trie_node{topic=Name} <- TrieNodes, Name =/= undefined]. [Name || #trie_node{topic=Name} <- TrieNodes, Name =/= undefined].
%%------------------------------------------------------------------------------
%% @doc Delete topic from trie %% @doc Delete topic from trie
%% @end
%%------------------------------------------------------------------------------
-spec delete(Topic :: binary()) -> ok. -spec delete(Topic :: binary()) -> ok.
delete(Topic) when is_binary(Topic) -> delete(Topic) when is_binary(Topic) ->
case mnesia:read(trie_node, Topic) of case mnesia:read(trie_node, Topic) of
@ -135,17 +112,12 @@ delete(Topic) when is_binary(Topic) ->
ok ok
end. end.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
%%------------------------------------------------------------------------------
%% @doc
%% @private %% @private
%% Add path to trie tree. %% @doc Add path to trie tree.
%%
%% @end
%%------------------------------------------------------------------------------
add_path({Node, Word, Child}) -> add_path({Node, Word, Child}) ->
Edge = #trie_edge{node_id=Node, word=Word}, Edge = #trie_edge{node_id=Node, word=Word},
case mnesia:read(trie_node, Node) of case mnesia:read(trie_node, Node) of
@ -162,14 +134,8 @@ add_path({Node, Word, Child}) ->
mnesia:write(#trie{edge=Edge, node_id=Child}) mnesia:write(#trie{edge=Edge, node_id=Child})
end. end.
%%------------------------------------------------------------------------------
%% @doc
%% @private %% @private
%% Match node with word or '+'. %% @doc Match node with word or '+'.
%%
%% @end
%%------------------------------------------------------------------------------
match_node(root, [<<"$SYS">>|Words]) -> match_node(root, [<<"$SYS">>|Words]) ->
match_node(<<"$SYS">>, Words, []); match_node(<<"$SYS">>, Words, []);
@ -187,13 +153,8 @@ match_node(NodeId, [W|Words], ResAcc) ->
end end
end, 'match_#'(NodeId, ResAcc), [W, '+']). end, 'match_#'(NodeId, ResAcc), [W, '+']).
%%------------------------------------------------------------------------------
%% @doc
%% @private %% @private
%% Match node with '#'. %% @doc Match node with '#'.
%%
%% @end
%%------------------------------------------------------------------------------
'match_#'(NodeId, ResAcc) -> 'match_#'(NodeId, ResAcc) ->
case mnesia:read(trie, #trie_edge{node_id=NodeId, word = '#'}) of case mnesia:read(trie, #trie_edge{node_id=NodeId, word = '#'}) of
[#trie{node_id=ChildId}] -> [#trie{node_id=ChildId}] ->
@ -202,13 +163,8 @@ match_node(NodeId, [W|Words], ResAcc) ->
ResAcc ResAcc
end. end.
%%------------------------------------------------------------------------------
%% @doc
%% @private %% @private
%% Delete paths from trie tree. %% @doc Delete paths from trie tree.
%%
%% @end
%%------------------------------------------------------------------------------
delete_path([]) -> delete_path([]) ->
ok; ok;
delete_path([{NodeId, Word, _} | RestPath]) -> delete_path([{NodeId, Word, _} | RestPath]) ->

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Utility functions.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd utility functions
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_util). -module(emqttd_util).
-export([apply_module_attributes/1, all_module_attributes/1, cancel_timer/1, -export([apply_module_attributes/1, all_module_attributes/1, cancel_timer/1,

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd erlang vm.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author @huangdan
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd erlang vm.
%%%
%%% @author huangdan
%%%-----------------------------------------------------------------------------
-module(emqttd_vm). -module(emqttd_vm).
-export([schedulers/0]). -export([schedulers/0]).

View File

@ -1,30 +1,24 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc emqttd websocket client
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqttd websocket client
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(emqttd_ws_client). -module(emqttd_ws_client).
-author("Feng Lee <feng@emqtt.io>").
-include("emqttd.hrl"). -include("emqttd.hrl").
-include("emqttd_protocol.hrl"). -include("emqttd_protocol.hrl").
@ -50,10 +44,7 @@
-define(WSLOG(Level, Format, Args, Req), -define(WSLOG(Level, Format, Args, Req),
lager:Level("WsClient(~s): " ++ Format, [Req:get(peer) | Args])). lager:Level("WsClient(~s): " ++ Format, [Req:get(peer) | Args])).
%%------------------------------------------------------------------------------
%% @doc Start WebSocket client. %% @doc Start WebSocket client.
%% @end
%%------------------------------------------------------------------------------
start_link(Req) -> start_link(Req) ->
PktOpts = emqttd:env(mqtt, packet), PktOpts = emqttd:env(mqtt, packet),
ParserFun = emqttd_parser:new(PktOpts), ParserFun = emqttd_parser:new(PktOpts),
@ -80,18 +71,12 @@ subscribe(CPid, TopicTable) ->
unsubscribe(CPid, Topics) -> unsubscribe(CPid, Topics) ->
gen_server:cast(CPid, {unsubscribe, Topics}). gen_server:cast(CPid, {unsubscribe, Topics}).
%%------------------------------------------------------------------------------
%% @private %% @private
%% @doc Start WebSocket client. %% @doc Upgrade WebSocket.
%% @end
%%------------------------------------------------------------------------------
upgrade(Req) -> upgrade(Req) ->
mochiweb_websocket:upgrade_connection(Req, fun ?MODULE:ws_loop/3). mochiweb_websocket:upgrade_connection(Req, fun ?MODULE:ws_loop/3).
%%------------------------------------------------------------------------------
%% @doc WebSocket frame receive loop. %% @doc WebSocket frame receive loop.
%% @end
%%------------------------------------------------------------------------------
ws_loop(<<>>, State, _ReplyChannel) -> ws_loop(<<>>, State, _ReplyChannel) ->
State; State;
ws_loop([<<>>], State, _ReplyChannel) -> ws_loop([<<>>], State, _ReplyChannel) ->
@ -118,9 +103,9 @@ ws_loop(Data, State = #wsocket_state{request = Req,
reset_parser(State = #wsocket_state{packet_opts = PktOpts}) -> reset_parser(State = #wsocket_state{packet_opts = PktOpts}) ->
State#wsocket_state{parser_fun = emqttd_parser:new(PktOpts)}. State#wsocket_state{parser_fun = emqttd_parser:new(PktOpts)}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% gen_server callbacks %% gen_server callbacks
%%%============================================================================= %%--------------------------------------------------------------------
init([WsPid, Req, ReplyChannel, PktOpts]) -> init([WsPid, Req, ReplyChannel, PktOpts]) ->
%%issue#413: trap_exit is unnecessary %%issue#413: trap_exit is unnecessary
@ -241,9 +226,9 @@ terminate(Reason, #wsclient_state{proto_state = ProtoState, keepalive = KeepAliv
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
%%%============================================================================= %%--------------------------------------------------------------------
%%% Internal functions %% Internal functions
%%%============================================================================= %%--------------------------------------------------------------------
with_proto_state(Fun, State = #wsclient_state{proto_state = ProtoState}) -> with_proto_state(Fun, State = #wsclient_state{proto_state = ProtoState}) ->
{ok, ProtoState1} = Fun(ProtoState), {ok, ProtoState1} = Fun(ProtoState),

View File

@ -1,28 +1,21 @@
%%%----------------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>. All Rights Reserved. %% Copyright (c) 2012-2016 Feng Lee <feng@emqtt.io>.
%%% %%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy %% Licensed under the Apache License, Version 2.0 (the "License");
%%% of this software and associated documentation files (the "Software"), to deal %% you may not use this file except in compliance with the License.
%%% in the Software without restriction, including without limitation the rights %% You may obtain a copy of the License at
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %%
%%% copies of the Software, and to permit persons to whom the Software is %% http://www.apache.org/licenses/LICENSE-2.0
%%% furnished to do so, subject to the following conditions: %%
%%% %% Unless required by applicable law or agreed to in writing, software
%%% The above copyright notice and this permission notice shall be included in all %% distributed under the License is distributed on an "AS IS" BASIS,
%%% copies or substantial portions of the Software. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% %% See the License for the specific language governing permissions and
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% limitations under the License.
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%--------------------------------------------------------------------
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% @doc Lager logger backend.
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% @author Feng Lee <feng@emqtt.io>
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%-----------------------------------------------------------------------------
%%% @doc emqtt lager backend
%%%
%%% @author Feng Lee <feng@emqtt.io>
%%%-----------------------------------------------------------------------------
-module(lager_emqtt_backend). -module(lager_emqtt_backend).
-behaviour(gen_event). -behaviour(gen_event).