Merge branch 'master' into dev

This commit is contained in:
Feng Lee 2015-06-02 12:56:13 +08:00
commit ebad80d690
12 changed files with 44 additions and 13 deletions

View File

@ -2,6 +2,14 @@
emqttd ChangeLog emqttd ChangeLog
================== ==================
0.8.2-alpha (2015-06-01)
-------------------------
Bugfix: issue #147 - WebSocket client cannot subscribe queue '$Q/queue/${clientId}'
Bugfix: issue #146 - emqttd_auth_ldap: fill(Username, UserDn) is not right
0.8.1-alpha (2015-05-28) 0.8.1-alpha (2015-05-28)
------------------------- -------------------------

View File

@ -37,6 +37,16 @@ emqttd is aimed to provide a solid, enterprise grade, extensible open-source MQT
* Passed eclipse paho interoperability tests * Passed eclipse paho interoperability tests
## Plugins
* [emqttd_auth_clientid](https://github.com/emqtt/emqttd/wiki/Authentication) - Authentication with ClientIds
* emqttd_auth_mysql - Authentication with MySQL
* emqttd_auth_ldap - Authentication with LDAP
* emqttd_mod_autosub - Subscribe some topics automatically when client connected
* [emqttd_mod_presence](https://github.com/emqtt/emqttd/wiki/Presence) - Publish presence message to $SYS topics when client connected or disconnected
* [emqttd_mod_rewrite](https://github.com/emqtt/emqttd/wiki/Rewrite) - Topics rewrite like HTTP rewrite module
## Design ## Design
![emqttd architecture](http://emqtt.io/static/img/Architecture.png) ![emqttd architecture](http://emqtt.io/static/img/Architecture.png)

View File

@ -1,7 +1,7 @@
{application, emqtt, {application, emqtt,
[ [
{description, "Erlang MQTT Common Library"}, {description, "Erlang MQTT Common Library"},
{vsn, "0.8.1"}, {vsn, "0.8.2"},
{modules, []}, {modules, []},
{registered, []}, {registered, []},
{applications, [ {applications, [

View File

@ -1,7 +1,7 @@
{application, emqttd, {application, emqttd,
[ [
{description, "Erlang MQTT Broker"}, {description, "Erlang MQTT Broker"},
{vsn, "0.8.1"}, {vsn, "0.8.2"},
{modules, []}, {modules, []},
{registered, []}, {registered, []},
{applications, [kernel, {applications, [kernel,

View File

@ -179,6 +179,7 @@ handle_call({register_mod, Type, Mod, Opts}, _From, State) ->
ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), [{Mod, ModState}|Mods]}), ets:insert(?ACCESS_CONTROL_TAB, {tab_key(Type), [{Mod, ModState}|Mods]}),
ok; ok;
{'EXIT', Error} -> {'EXIT', Error} ->
lager:error("Access Control: register ~s error - ~p", [Mod, Error]),
{error, Error} {error, Error}
end; end;
_ -> _ ->

View File

@ -82,10 +82,7 @@ ldap_bind(LDAP, UserDn, Password) ->
end. end.
fill(Username, UserDn) -> fill(Username, UserDn) ->
lists:append(lists:map( re:replace(UserDn, "\\$u", Username, [global, {return, list}]).
fun("$u") -> Username;
(S) -> S
end, string:tokens(UserDn, ",="))).
description() -> description() ->
"LDAP Authentication Module". "LDAP Authentication Module".

View File

@ -145,6 +145,10 @@ handle_info({redeliver, {?PUBREL, PacketId}}, #state{proto_state = ProtoState} =
{ok, ProtoState1} = emqttd_protocol:redeliver({?PUBREL, PacketId}, ProtoState), {ok, ProtoState1} = emqttd_protocol:redeliver({?PUBREL, PacketId}, ProtoState),
{noreply, State#state{proto_state = ProtoState1}}; {noreply, State#state{proto_state = ProtoState1}};
handle_info({subscribe, Topic, Qos}, #state{proto_state = ProtoState} = State) ->
{ok, ProtoState1} = emqttd_protocol:handle({subscribe, Topic, Qos}, ProtoState),
{noreply, State#state{proto_state = ProtoState1}};
handle_info({stop, duplicate_id, _NewPid}, State=#state{proto_state = ProtoState}) -> handle_info({stop, duplicate_id, _NewPid}, State=#state{proto_state = ProtoState}) ->
lager:error("Shutdown for duplicate clientid: ~s", [emqttd_protocol:clientid(ProtoState)]), lager:error("Shutdown for duplicate clientid: ~s", [emqttd_protocol:clientid(ProtoState)]),
stop({shutdown, duplicate_id}, State); stop({shutdown, duplicate_id}, State);
@ -169,7 +173,8 @@ handle_info({keepalive, timeout}, State = #state{request = Req, keepalive = Keep
handle_info({'EXIT', WsPid, Reason}, State = #state{ws_pid = WsPid}) -> handle_info({'EXIT', WsPid, Reason}, State = #state{ws_pid = WsPid}) ->
stop(Reason, State); stop(Reason, State);
handle_info(_Info, State) -> handle_info(Info, State = #state{request = Req}) ->
lager:critical("Client(WebSocket) ~s: Unexpected Info - ~p", [Req:get(peer), Info]),
{noreply, State}. {noreply, State}.
terminate(Reason, #state{proto_state = ProtoState, keepalive = KeepAlive}) -> terminate(Reason, #state{proto_state = ProtoState, keepalive = KeepAlive}) ->

View File

@ -9,8 +9,9 @@
]}, ]},
{emqttd_auth_mysql, [ {emqttd_auth_mysql, [
{users_table, mqtt_users}, {users_table, mqtt_users},
{password_hash, plain},
{field_mapper, [ {field_mapper, [
{username, username}, {username, username},
{password, password, plain} {password, password}
]} ]}
]} ]}

View File

@ -38,15 +38,19 @@
init(Opts) -> init(Opts) ->
Mapper = proplists:get_value(field_mapper, Opts), Mapper = proplists:get_value(field_mapper, Opts),
{ok, #state{user_table = proplists:get_value(user_table, Opts, mqtt_users), {ok, #state{user_table = proplists:get_value(user_table, Opts),
name_field = proplists:get_value(username, Mapper), name_field = proplists:get_value(username, Mapper),
pass_field = proplists:get_value(password, Mapper), pass_field = proplists:get_value(password, Mapper),
pass_hash = proplists:get_value(Opts, password_hash)}}. pass_hash = proplists:get_value(password_hash, Opts)}}.
check(#mqtt_client{username = undefined}, _Password, _State) -> check(#mqtt_client{username = undefined}, _Password, _State) ->
{error, "Username undefined"}; {error, "Username undefined"};
check(#mqtt_client{username = <<>>}, _Password, _State) ->
{error, "Username undefined"};
check(_Client, undefined, _State) -> check(_Client, undefined, _State) ->
{error, "Password undefined"}; {error, "Password undefined"};
check(_Client, <<>>, _State) ->
{error, "Password undefined"};
check(#mqtt_client{username = Username}, Password, check(#mqtt_client{username = Username}, Password,
#state{user_table = UserTab, pass_hash = Type, #state{user_table = UserTab, pass_hash = Type,
name_field = NameField, pass_field = PassField}) -> name_field = NameField, pass_field = PassField}) ->

View File

@ -40,7 +40,7 @@
start(_StartType, _StartArgs) -> start(_StartType, _StartArgs) ->
Env = application:get_all_env(), Env = application:get_all_env(),
emqttd_access_control:register_mod(auth, emqttd_auth_mysql, Env), ok = emqttd_access_control:register_mod(auth, emqttd_auth_mysql, Env),
supervisor:start_link({local, ?MODULE}, ?MODULE, []). supervisor:start_link({local, ?MODULE}, ?MODULE, []).
prep_stop(State) -> prep_stop(State) ->

View File

@ -9,7 +9,12 @@
% {encoding, utf8} % {encoding, utf8}
% ]}, % ]},
% {emqttd_auth_mysql, [ % {emqttd_auth_mysql, [
% {user_table, mqtt_users} % {users_table, mqtt_users},
% {password_hash, plain},
% {field_mapper, [
% {username, username},
% {password, password}
% ]}
% ]} % ]}
% %
% {emqttd_dashboard, [ % {emqttd_dashboard, [

View File

@ -4,7 +4,7 @@
{lib_dirs, ["../apps", "../deps", "../plugins"]}, {lib_dirs, ["../apps", "../deps", "../plugins"]},
{erts, [{mod_cond, derived}, {app_file, strip}]}, {erts, [{mod_cond, derived}, {app_file, strip}]},
{app_file, strip}, {app_file, strip},
{rel, "emqttd", "0.8.1", {rel, "emqttd", "0.8.2",
[ [
kernel, kernel,
stdlib, stdlib,