From e77d25b273d107748e9684fdb6b778eab9c4d5de Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Wed, 10 Dec 2014 18:21:37 +0800 Subject: [PATCH 01/10] author... --- LICENSE | 2 +- apps/emqtt/include/emqtt.hrl | 4 ++-- apps/emqtt/include/emqtt_log.hrl | 2 +- apps/emqtt/include/emqtt_topic.hrl | 2 +- apps/emqtt/src/emqtt.erl | 2 +- apps/emqtt/src/emqtt_app.erl | 4 ++-- apps/emqtt/src/emqtt_auth.erl | 4 ++-- apps/emqtt/src/emqtt_auth_anonymous.erl | 4 ++-- apps/emqtt/src/emqtt_auth_internal.erl | 4 +++- apps/emqtt/src/emqtt_client.erl | 4 +++- apps/emqtt/src/emqtt_cm.erl | 4 ++-- apps/emqtt/src/emqtt_ctl.erl | 4 +++- apps/emqtt/src/emqtt_db.erl | 4 +++- apps/emqtt/src/emqtt_frame.erl | 2 +- apps/emqtt/src/emqtt_http.erl | 2 +- apps/emqtt/src/emqtt_keep_alive.erl | 2 +- apps/emqtt/src/emqtt_monitor.erl | 2 +- apps/emqtt/src/emqtt_net.erl | 2 +- apps/emqtt/src/emqtt_pubsub.erl | 2 +- apps/emqtt/src/emqtt_retained.erl | 2 +- apps/emqtt/src/emqtt_sup.erl | 2 +- apps/emqtt/src/emqtt_topic.erl | 2 +- 22 files changed, 35 insertions(+), 27 deletions(-) diff --git a/LICENSE b/LICENSE index 0e6702163..fe58b384a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014, Feng Lee +Copyright (c) 2014, Feng Lee Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/include/emqtt.hrl b/apps/emqtt/include/emqtt.hrl index ea8e9571d..dbffbe0e4 100644 --- a/apps/emqtt/include/emqtt.hrl +++ b/apps/emqtt/include/emqtt.hrl @@ -1,5 +1,5 @@ %%------------------------------------------------------------------------------ -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,7 @@ %% --------------------------------- %% banner %% --------------------------------- --define(COPYRIGHT, "Copyright (C) 2014, Feng Lee"). +-define(COPYRIGHT, "Copyright (C) 2014, Feng Lee"). -define(LICENSE_MESSAGE, "Licensed under MIT"). diff --git a/apps/emqtt/include/emqtt_log.hrl b/apps/emqtt/include/emqtt_log.hrl index 707115ee1..cb9215ebc 100644 --- a/apps/emqtt/include/emqtt_log.hrl +++ b/apps/emqtt/include/emqtt_log.hrl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/include/emqtt_topic.hrl b/apps/emqtt/include/emqtt_topic.hrl index 059d53b71..c31ea8556 100644 --- a/apps/emqtt/include/emqtt_topic.hrl +++ b/apps/emqtt/include/emqtt_topic.hrl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt.erl b/apps/emqtt/src/emqtt.erl index 42055f2f5..7931e8416 100644 --- a/apps/emqtt/src/emqtt.erl +++ b/apps/emqtt/src/emqtt.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt_app.erl b/apps/emqtt/src/emqtt_app.erl index 8d446be36..b8fac497f 100644 --- a/apps/emqtt/src/emqtt_app.erl +++ b/apps/emqtt/src/emqtt_app.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,7 @@ -module(emqtt_app). --author('ery.lee@gmail.com'). +-author('feng@slimchat.io'). -include("emqtt_log.hrl"). diff --git a/apps/emqtt/src/emqtt_auth.erl b/apps/emqtt/src/emqtt_auth.erl index ede016cda..131647cf9 100644 --- a/apps/emqtt/src/emqtt_auth.erl +++ b/apps/emqtt/src/emqtt_auth.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,7 @@ -module(emqtt_auth). --author('feng.lee@slimchat.io'). +-author('feng@slimchat.io'). -include("emqtt.hrl"). diff --git a/apps/emqtt/src/emqtt_auth_anonymous.erl b/apps/emqtt/src/emqtt_auth_anonymous.erl index 8beb7463c..a823eeef3 100644 --- a/apps/emqtt/src/emqtt_auth_anonymous.erl +++ b/apps/emqtt/src/emqtt_auth_anonymous.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,7 @@ -module(emqtt_auth_anonymous). --author('feng.lee@slimchat.io'). +-author('feng@slimchat.io'). -export([init/1, add/2, diff --git a/apps/emqtt/src/emqtt_auth_internal.erl b/apps/emqtt/src/emqtt_auth_internal.erl index 109e87d9f..444b8cee3 100644 --- a/apps/emqtt/src/emqtt_auth_internal.erl +++ b/apps/emqtt/src/emqtt_auth_internal.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ -module(emqtt_auth_internal). +-author('feng@slimchat.io'). + -include("emqtt.hrl"). -export([init/1, diff --git a/apps/emqtt/src/emqtt_client.erl b/apps/emqtt/src/emqtt_client.erl index ba487177c..58c9dbc46 100644 --- a/apps/emqtt/src/emqtt_client.erl +++ b/apps/emqtt/src/emqtt_client.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ -module(emqtt_client). +-author('feng@slimchat.io'). + -behaviour(gen_server). -export([start_link/1, info/1, go/2, stop/2]). diff --git a/apps/emqtt/src/emqtt_cm.erl b/apps/emqtt/src/emqtt_cm.erl index bf3b4469d..28f6ef240 100644 --- a/apps/emqtt/src/emqtt_cm.erl +++ b/apps/emqtt/src/emqtt_cm.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,7 @@ %client manager -module(emqtt_cm). --author('feng.lee@slimchat.io'). +-author('feng@slimchat.io'). -behaviour(gen_server). diff --git a/apps/emqtt/src/emqtt_ctl.erl b/apps/emqtt/src/emqtt_ctl.erl index 01bbed456..9962ed73d 100644 --- a/apps/emqtt/src/emqtt_ctl.erl +++ b/apps/emqtt/src/emqtt_ctl.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ -module(emqtt_ctl). +-author('feng@slimchat.io'). + -include("emqtt.hrl"). -include("emqtt_log.hrl"). diff --git a/apps/emqtt/src/emqtt_db.erl b/apps/emqtt/src/emqtt_db.erl index aa348fe7a..0b5f508ad 100644 --- a/apps/emqtt/src/emqtt_db.erl +++ b/apps/emqtt/src/emqtt_db.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,8 @@ -module(emqtt_db). +-author('feng@slimchat.io'). + -export([init/0, stop/0]). init() -> diff --git a/apps/emqtt/src/emqtt_frame.erl b/apps/emqtt/src/emqtt_frame.erl index 5b93ab3dd..aa6b31e20 100644 --- a/apps/emqtt/src/emqtt_frame.erl +++ b/apps/emqtt/src/emqtt_frame.erl @@ -1,5 +1,5 @@ %%------------------------------------------------------------------------------ -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt_http.erl b/apps/emqtt/src/emqtt_http.erl index fab3ae4c4..3dcfa0f44 100644 --- a/apps/emqtt/src/emqtt_http.erl +++ b/apps/emqtt/src/emqtt_http.erl @@ -1,5 +1,5 @@ %%------------------------------------------------------------------------------ -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt_keep_alive.erl b/apps/emqtt/src/emqtt_keep_alive.erl index 7eb6b7f25..d00841625 100644 --- a/apps/emqtt/src/emqtt_keep_alive.erl +++ b/apps/emqtt/src/emqtt_keep_alive.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt_monitor.erl b/apps/emqtt/src/emqtt_monitor.erl index fa15d8b11..4c992aacb 100644 --- a/apps/emqtt/src/emqtt_monitor.erl +++ b/apps/emqtt/src/emqtt_monitor.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt_net.erl b/apps/emqtt/src/emqtt_net.erl index 545e31061..d48f8884b 100644 --- a/apps/emqtt/src/emqtt_net.erl +++ b/apps/emqtt/src/emqtt_net.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt_pubsub.erl b/apps/emqtt/src/emqtt_pubsub.erl index 4eccbe356..ef60674fa 100644 --- a/apps/emqtt/src/emqtt_pubsub.erl +++ b/apps/emqtt/src/emqtt_pubsub.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt_retained.erl b/apps/emqtt/src/emqtt_retained.erl index e1f79be94..5a1df1e4d 100644 --- a/apps/emqtt/src/emqtt_retained.erl +++ b/apps/emqtt/src/emqtt_retained.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt_sup.erl b/apps/emqtt/src/emqtt_sup.erl index f8e0af072..d24059f31 100644 --- a/apps/emqtt/src/emqtt_sup.erl +++ b/apps/emqtt/src/emqtt_sup.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal diff --git a/apps/emqtt/src/emqtt_topic.erl b/apps/emqtt/src/emqtt_topic.erl index b40fc3552..5cd150edb 100644 --- a/apps/emqtt/src/emqtt_topic.erl +++ b/apps/emqtt/src/emqtt_topic.erl @@ -1,5 +1,5 @@ %%----------------------------------------------------------------------------- -%% Copyright (c) 2014, Feng Lee +%% Copyright (c) 2014, Feng Lee %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal From 20fb39cf3b99758337ee15acf58186b16e83110b Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Wed, 10 Dec 2014 19:20:09 +0800 Subject: [PATCH 02/10] list -> binary --- apps/emqtt/include/emqtt_frame.hrl | 2 +- apps/emqtt/src/emqtt_auth.erl | 14 ++++++++++---- apps/emqtt/src/emqtt_client.erl | 6 +++--- apps/emqtt/src/emqtt_frame.erl | 2 +- apps/emqtt/src/emqtt_http.erl | 13 ++++++------- apps/emqtt/src/emqtt_net.erl | 2 +- apps/emqtt/src/emqtt_protocol.erl | 5 +++++ apps/emqtt/src/emqtt_sup.erl | 9 +-------- apps/emqtt/src/emqtt_topic.erl | 4 ++-- 9 files changed, 30 insertions(+), 27 deletions(-) create mode 100644 apps/emqtt/src/emqtt_protocol.erl diff --git a/apps/emqtt/include/emqtt_frame.hrl b/apps/emqtt/include/emqtt_frame.hrl index 82c7d196c..e00191261 100644 --- a/apps/emqtt/include/emqtt_frame.hrl +++ b/apps/emqtt/include/emqtt_frame.hrl @@ -18,7 +18,7 @@ %% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% --define(PROTOCOL_NAMES, [{3, "MQIsdp"}, {4, "MQTT"}]). +-define(PROTOCOL_NAMES, [{3, <<"MQIsdp">>}, {4, <<"MQTT">>}]). -define(MQTT_PROTO_MAJOR, 3). -define(MQTT_PROTO_MINOR, 1). diff --git a/apps/emqtt/src/emqtt_auth.erl b/apps/emqtt/src/emqtt_auth.erl index 131647cf9..0905ef8ee 100644 --- a/apps/emqtt/src/emqtt_auth.erl +++ b/apps/emqtt/src/emqtt_auth.erl @@ -30,7 +30,7 @@ -export([start_link/0, add/2, - check/2, + check/1, check/2, delete/1]). -behavior(gen_server). @@ -42,9 +42,15 @@ terminate/2, code_change/3]). +-define(TAB, ?MODULE). + start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). +-spec check({Usename :: binary(), Password :: binary()}) -> true | false. +check({Username, Password}) -> + execute(check, [Username, Password]). + -spec check(Usename :: binary(), Password :: binary()) -> true | false. check(Username, Password) -> execute(check, [Username, Password]). @@ -58,15 +64,15 @@ delete(Username) -> execute(delete, [Username]). execute(F, Args) -> - [{_, M}] = ets:lookup(emqtt_auth, mod), + [{_, M}] = ets:lookup(?TAB, mod), apply(M, F, Args). init([]) -> {ok, {Name, Opts}} = application:get_env(auth), AuthMod = authmod(Name), ok = AuthMod:init(Opts), - ets:new(emqtt_auth, [named_table, protected]), - ets:insert(emqtt_quth, {mod, AuthMod}), + ets:new(?TAB, [named_table, protected]), + ets:insert(?TAB, {mod, AuthMod}), ?PRINT("emqtt authmod is ~p", [AuthMod]), {ok, undefined}. diff --git a/apps/emqtt/src/emqtt_client.erl b/apps/emqtt/src/emqtt_client.erl index d6b62cfe0..daa322fa7 100644 --- a/apps/emqtt/src/emqtt_client.erl +++ b/apps/emqtt/src/emqtt_client.erl @@ -242,7 +242,7 @@ process_request(?CONNECT, keep_alive = AlivePeriod, client_id = ClientId } = Var}, #state{socket = Sock} = State) -> {ReturnCode, State1} = - case {ProtoVersion =:= ?MQTT_PROTO_MAJOR, + case {lists:member(ProtoVersion, proplists:get_keys(?PROTOCOL_NAMES)), valid_client_id(ClientId)} of {false, _} -> {?CONNACK_PROTO_VER, State}; @@ -264,7 +264,7 @@ process_request(?CONNECT, end end, ?INFO("recv conn...:~p", [ReturnCode]), - send_frame(Sock, #mqtt_frame{ fixed = #mqtt_frame_fixed{ type = ?CONNACK}, + send_frame(Sock, #mqtt_frame{ fixed = #mqtt_frame_fixed{ type = ?CONNACK}, variable = #mqtt_frame_connack{ return_code = ReturnCode }}), {ok, State1}; @@ -428,7 +428,7 @@ stop(Reason, State ) -> {stop, Reason, State}. valid_client_id(ClientId) -> - ClientIdLen = length(ClientId), + ClientIdLen = size(ClientId), 1 =< ClientIdLen andalso ClientIdLen =< ?CLIENT_ID_MAXLEN. handle_retained(?PUBLISH, #mqtt_frame{fixed = #mqtt_frame_fixed{retain = false}}) -> diff --git a/apps/emqtt/src/emqtt_frame.erl b/apps/emqtt/src/emqtt_frame.erl index aa6b31e20..660e2c6f8 100644 --- a/apps/emqtt/src/emqtt_frame.erl +++ b/apps/emqtt/src/emqtt_frame.erl @@ -161,7 +161,7 @@ parse_utf(Bin, _) -> parse_utf(Bin). parse_utf(<>) -> - {binary_to_list(Str), Rest}. + {Str, Rest}. parse_msg(Bin, 0) -> {undefined, Bin}; diff --git a/apps/emqtt/src/emqtt_http.erl b/apps/emqtt/src/emqtt_http.erl index cf4918090..2458c4241 100644 --- a/apps/emqtt/src/emqtt_http.erl +++ b/apps/emqtt/src/emqtt_http.erl @@ -26,6 +26,8 @@ -include("emqtt.hrl"). +-include("emqtt_log.hrl"). + -import(proplists, [get_value/2, get_value/3]). -export([handle/1]). @@ -43,8 +45,8 @@ handle(Req) -> handle('POST', "/mqtt/publish", Req) -> Params = mochiweb_request:parse_post(Req), - error_logger:info_msg("~p~n", [Params]), - Topic = get_value("topic", Params), + ?INFO("~p~n", [Params]), + Topic = list_to_binary(get_value("topic", Params)), Message = list_to_binary(get_value("message", Params)), emqtt_pubsub:publish(#mqtt_msg { retain = 0, @@ -66,12 +68,9 @@ authorized(Req) -> undefined -> false; "Basic " ++ BasicAuth -> - {Username, Password} = user_passwd(BasicAuth), - emqtt_auth:check(Username, Password) + emqtt_auth:check(user_passwd(BasicAuth)) end. user_passwd(BasicAuth) -> - [U, P] = binary:split(base64:decode(BasicAuth), <<":">>), - {binary_to_list(U), binary_to_list(P)}. - + list_to_tuple(binary:split(base64:decode(BasicAuth), <<":">>)). diff --git a/apps/emqtt/src/emqtt_net.erl b/apps/emqtt/src/emqtt_net.erl index c4061fd31..e6620c3b7 100644 --- a/apps/emqtt/src/emqtt_net.erl +++ b/apps/emqtt/src/emqtt_net.erl @@ -24,7 +24,7 @@ -author('feng@slimchat.io'). --export([tcp_name/3, tcp_host/1, getaddr/2, port_to_listeners/1]). +-export([tcp_name/3, tcp_host/1, getopts/2, setopts/2, getaddr/2, port_to_listeners/1]). -export([connection_string/2]). diff --git a/apps/emqtt/src/emqtt_protocol.erl b/apps/emqtt/src/emqtt_protocol.erl new file mode 100644 index 000000000..468b70a22 --- /dev/null +++ b/apps/emqtt/src/emqtt_protocol.erl @@ -0,0 +1,5 @@ + +-module(emqtt_protocol). + +-include("emqtt_frame.hrl"). + diff --git a/apps/emqtt/src/emqtt_sup.erl b/apps/emqtt/src/emqtt_sup.erl index 7a0d52b75..de3d053b3 100644 --- a/apps/emqtt/src/emqtt_sup.erl +++ b/apps/emqtt/src/emqtt_sup.erl @@ -60,12 +60,5 @@ start_child(Mod, Type) when is_atom(Mod) and is_atom(Type) -> %% =================================================================== init([]) -> - {ok, { {one_for_all, 5, 10}, [ - ?CHILD(emqtt_cm, worker), - ?CHILD(emqtt_monitor, worker), - ?CHILD(emqtt_auth, worker), - ?CHILD(emqtt_retained, worker), - ?CHILD(emqtt_pubsub, worker), - ?CHILD(emqtt_registry, worker)]} - }. + {ok, { {one_for_all, 5, 10}, [] } }. diff --git a/apps/emqtt/src/emqtt_topic.erl b/apps/emqtt/src/emqtt_topic.erl index 5c45e5868..29d9d865d 100644 --- a/apps/emqtt/src/emqtt_topic.erl +++ b/apps/emqtt/src/emqtt_topic.erl @@ -111,7 +111,7 @@ validate({subscribe, Topic}) when is_binary(Topic) -> valid(words(Topic)); validate({publish, Topic}) when is_binary(Topic) -> Words = words(Topic), - valid(Words) and (not include_wildcard(Words)). + valid(Words) and (not include_wildcard(Topic)). triples(B) when is_binary(B) -> triples(binary_to_list(B), []). @@ -152,5 +152,5 @@ include_wildcard(<<$#, _T/binary>>) -> true; include_wildcard(<<$+, _T/binary>>) -> true; include_wildcard(<<_H, T/binary>>) -> include_wildcard(T). -l2b(L) when is_list(L) -> list_to_binary(L). +l2b(L) -> list_to_binary(L). From 95f2ffe79322cb79e71fbde622fd2728115d67b7 Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Wed, 10 Dec 2014 19:42:03 +0800 Subject: [PATCH 03/10] design --- README.md | 88 ++++++++++++++++++++++++++------------------------ doc/emqtt.png | Bin 0 -> 8953 bytes 2 files changed, 45 insertions(+), 43 deletions(-) create mode 100644 doc/emqtt.png diff --git a/README.md b/README.md index 030a92698..4eb7d71b7 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,76 @@ -emqtt -===== +# eMQTT -erlang mqtt broker. +eMQTT is a scalable, fault-tolerant and extensible mqtt broker written in Erlang/OTP. -requires -======== +eMQTT requires Erlang R17+. -erlang R15B+ +## Startup in Five Minutes -git client +``` + $ git clone git://github.com/slimpp/emqtt.git -build -======= + $ cd emqtt -make + $ make && make generate -release -======= + $ cd rel/emqtt -make generate + $ ./bin/emqtt console +``` -deloy -===== +## Deploy and Start -cp -R rel/emqtt $INSTALL_DIR +### start -start -====== +``` + cp -R rel/emqtt $INSTALL_DIR -cd $INSTALL_DRI/emqtt + cd $INSTALL_DIR/emqtt -./bin/emqtt console + ./bin/emqtt start -or +``` -./bin/emqtt start +### stop -status -====== +``` + ./bin/emqtt stop -./bin/emqtt_ctl status +``` -stop -==== +## HTTP API -./bin/emqtt stop +eMQTT support http to publish message. -logs -==== +Example: -log/* +``` + curl -v --basic -u user:passwd -d "topic=/a/b/c&message=hello from http..." -k http://localhost:8883/mqtt/publish +``` -http api -======== +### URL -curl -v --basic -u user:passwd -d "topic=/abc&message=akakakk&qos=0" -k http://localhost:8883/mqtt/publish +``` + HTTP POST http://host:8883/mqtt/publish +``` -design -===== +### Parameters -https://github.com/slimpp/emqtt/wiki +Name | Description +-----|------------- +topic | MQTT Topic +message | Text Message -author -===== +## Design -Ery Lee +[Design Wiki](https://github.com/slimpp/emqtt/wiki) - -license -====== +## License The MIT License (MIT) +## Author +===== + +feng at slimchat.io + diff --git a/doc/emqtt.png b/doc/emqtt.png new file mode 100644 index 0000000000000000000000000000000000000000..df6462e86033a8252334e946071efb14effcac64 GIT binary patch literal 8953 zcmb7q2UL^U);7o|j7m{Z7&;>&B27SgRjE=!?*yfaK|nf4(LqIeZ_-6XAd~&mcQW@)e)PLHr-Vo-hkN=o+HS(?$Pod$p z_sQ>b`de=~ z1A1jE*(fxYviqRPIxoh{1={m{cPlN}e(u)Vtw};}W)tHqABn>5WwtXU92gQ3D=Ly^ zCK3fWDe>ivD9LkUGUCfc7zqi2oH+W|L;LokqM}`i{OFxg*cERBV`JmTj|&bZ_PCUp zGpohM=q@!id9QjK?L|iqs_06se=!(6*oq7dWs>$>sqt9$T=}*^T5B`klkVf=qxV6B zQP%f%ow8X*wUD**o6L(9fpNMAF|Iq-^lN+`&k{C=uPo0L=crJ_) zZymg*E3e){&*fLzAAvBu{Az@zt~pq6*+2aUH{f;cI3B*IQ#cm=%>(_g(lMaGAUjC0<~hIP}Um2wdeCVOE;qzcd3Q zRR1>qyWgM2z`5qX{ayf$Nr=wh{`7khM)VB=dLw!PK@KjvKR{p{#Bn+>ME{p};Fd#+8?y?_7S+MZp)<@*3c9=o^RVy?yg#^ceWg~F2h0#<*J za?TA$o{|@@T(OmEo1APgDuFId-3cNWg{CAVX^uy0DGi0CDAMK2FW7)O~m@izoaIlJA8^?}Q zTXvN`Y&zadYN#kJ>!7RH=hxBG6Y<4A^1-uE2SeJV20yyj-6aI{3c@l1vg#k%`fLY7 z0zUGo>hJFw@>yRlS7Q{vPxw)^#T^!^t#P!>5GbE(6txvhu?@4b#n4*e*jidzEYO}* z=g<2t<>v{=m5o(Cff?adB3XDK&m+@^Rji9*4(dH|qvZ3CYjp+Yw}&lH7V|PEo~_jh zSk(9(6XuHoyp9hEn`aJjsL6snpPdo=S$q7^?qpZHjw{?#yEUZj!_e6DN*qKkMcB4e z>9zOa-bSjpv(xH=5>&kqAs291Rf||qfGY(A)E_eK5eOzlh6JVUMPml|zHN8O=Y&ts zw-6cf7Af92o4DewNng(w!li3xZIf(gL_0?ZUo(u&+_%D6b#!!~#$CHA90pn=SqqC; zMC`&Vq@|=xuL|VcLSrXB`_3D8oii+f@>9I$5XZXfp`5TbeW*wMS53CilSfVqec48q z{>a;f6&3oJFB!6Ctlb@4E92FA(j~q-%+9qs#Y$E-Fl-U!kUH{Yb zwt#@sGNx!C4?;stt);1XG~95^CI2?yXuodnN7&N2NEXSf4f>mO4f7e#XlZF@JO#`u z`EK3P*5Yh9xB0mL`y;pEGTW|1%ai@#O+$r%1>w&L37du68*S``+|j&8%a$hvXT7Fd zBdD}i%pX?YCTPZy2@6MCa!ZbkSGys%I&*f%CXXv2nQ}Dphc0nZ3XYEO&GPm2^_7(s zI&Q56F^o#(O`)6wwmY5pko(=mmRA15mu;82=cA6T%Y`Ki0<`%Ma{H04BetCr@<*=c z?01Hu;>(k0VgAjg8Qj8~ogE$3hnrntp`jIxWioX}#pZ;=tzPDc)|M~^RB8Rj?e>GU z2EjEOl?bMUq$KX%(9fUm5)#9+W;-|_YizQU#DlukTtV|BHj`GobFFZ<1G1ogyK}nIta^~ zo34x|yjnIgG4b)&mOXx7HgncJF4dMi4mf%d(G?i7oj4y)5;&{qaMZ7KQe0cM;s^JF z=SO*9CoTxgM4BxHk2Q}TASOy522qC1pbV+I29A#p)`s5}M%d3T@{@(qW5gqo6$YzH zc6N4gM!r~&;SLw*v;4jfcPhGcdXGn8CHc!-`yzH{p8yZMLHQSz%D#$^236xjWc zK@>VZi#GvsK3;HAH?h}f?r<*2IH{pHoT&gF_~Y=CNkLJo@7DdB77Vh zgRJd#`~%~CF-Z}lz;1f&u8eS^JWq~~dbs0I zC!1&TS+QuZl3JlykxG9X3vKQ1e&?u^;o#m0$m|b2t?kH@t<017OV240>GL0EMUAP) zU7DzR;s&WAEB*L4l{LwG_@m&=nN=O~w~mk20+X7^$SI?}$Rc`~85s%l@+Z|DPwvh< zg+(t$M_(kc78ewJHGofc6l8|fKiwnDqEOI_%Lz0$;#zNT!4e$kmW&Dz6Xn^*t1FZ4 zjkC=W28QDhcpd9%DsQ zYBW5q*s9Js&Xr)>X|!|w_|pwU;#8%d(Ovj)u1#6+jDN=>b;nK;N}*(bFiE4)_6c_^-HBy%(z zx$bp~PsZCTl|buee5#&KD>H_)m#fMifxCRYz2t~QqZm2=eVO%7WUfl7Vozf8;?mNM zQ9_s>A>0|!yJ{*?Yza+ykj%tkYewq~Nw>MJUilO7L4)#=t!-^xQDuPSohTBTXyhwo zF|JjX4FO=h7VmzvzrA@+-#!|c9)Gira$xx3S5XZ!srBA~$RFWB#p_zjYu3SzueUH* z#*5RH+xI5kdG1C`pQmt0x>RnDaNzckk!#bSJZ&Wt%;(^pmT{LfIpes#zW#y_Sl7Bv zWY99INt*ERNXO%~X&92_cUgSWlf6OXF48f-*|&ZB4Yxa|1`gt@2bL(l%lj!3b7x^; z;p_!^iISMCkId%k^jtZ#XBcxLn8jBCf(`kOdi%$XnK*wdy+h4RN$#R$AYvD0uumpR(HCv1SsxE95i%NU(;>GT`8)W*aEW&9DP5X!^>$cLn z>on6d9dWt$ms;&(#m-rIdso$(=){dC8mqs_(@e#Du5{9DHJvae92}@q%?@iYn~dQ+ zeYh~>+dV3&=tM>lyX0=WYUxc2kIQ^sip4?_62?#xCXFD~dge5+LST8UqD4B@-`1v8 zJY`ZeR8~}MPnYssNrpJuAB`|?yA8;qhjw>|rFC7Rm`WF|#Ur3%bew#XZ zAmhEBC3Y#hZdV@gz#x9O8P`1z5A$(oth$G=MQXXBb8@&}x^tdyMF*_E^>bSkyBAc@ zD|>@}U}$J)^X|}Ivt}%B0v&22vR$I4<4NImL;5yiw}+;9tUm3go}9lX;d@kPI=yW> z$!vCDp?qiHttBZ;{Wj!v^QeDpT-=aaLKwmFcYX}6CeiT3NJ(C5w*F3}qe1MNlhtaf z@iG^t(5NI)=gHVG9jwA}xY&aKFvs)4OoWkv!Il3XeJ3i5f6{C^*mI)t_z!VFB>4X+ zI({V%n&1BZ;#X!sGMtK;UyBZ+viPSs(1eqoDvy7QgMW&SUq=lj$=@}_sTpxD#CU%# zI)16M5aj>RS$|)RUrU;wTIp{qb!tYO%YW;)T(>sgwn$dIj=bmUxEfIeI^k6CIx6Z| zsCb(%V2yytamMT;90op=mfo^@nW$vWToXtaGT5(+P&&sxJ{*C7*0?WfienY8Zd-T8 z^W^8}1Nm7li;xJYWe*wbwL+R_)XdxwZ>{<8!EUBK#=0#sVFOu9nwJ1gJBk)UwpcNW zIVK-!zqw@UKc@^8=R39wWVGyJb}?OS8KGg+Gvg1K%l-rBKX;RLFJFG=oAoBf?1d2( zn~Ve(*DKu|T(9{Uo%)wy{8aU{#Z=IhTc+V)%fC55y`Le#5*>a@Um4JYNbLY+hEd^QtQaw&6b;uPZ9$sEI!YgSOYLD|* zWo6Ti$rRdD>g~!${AIBXfem7|d?n|JPk**6cMyt*it-}N&d<-olGs^TR&wHoo0*=A zOR_`)#q(Gwp-G@2w4&nnJWdF1SSY9krGt@7#79T>J(#Wp3~3npYOuP|z{bvw7Dn=j zcmCXYO;9XhC0tjpzH2l9S^?A(;s_RD-4?E#W7-RfjT{GuLh1(>+!aPja?!r2sVNlJ zGu1C4$92e+3^Xq)tR`xG?%cVv>9M$GAEy^fQQR8~th52|G3^p|UytcNsqM{-` z{<4V)6q?~1Nux=O3i{neLReT>D@`JsO%novXlcnEY$g7&X<=j$<8C5wOI+NDIw?M0 zQCWF^fm0by>OJ`-MZ|WdkgcbqgXhK#mmw|&dir8x#9e0FE@SAkSDMuPR9tp2+g0$S6VMjQIsGET2BxM=moD9blV)K< z!@_`xteXWAi6jqdM2U@ZVo2Qo5D^jK;pwn8;ufR?r5o(SD7U1fBqwJRxHUW*HUN(K z^CS~KddOLQ6_BL^Gaj~_{Z7U}J+4pA1iJ#sc0DAb(KmU~R%iY-6`0L&a zG71@ao~fU%#KGR8*Y0(vPXFtD?)&$T4p!HbYiguuAn{=3>iOm5CU~WnOHGS}KXQY~ zT(>JHe0o8a(J%oNhtJmBC9s1Q78dE5nVCj%q*=AKGBPr0AgPvX%Xr?jqCOObh?11> z@bPJ=s;*;@2bc=bj`%LRxVX3!eAQRU$*Gt|(~P)7BKAEjxPe-kwe_hcx!b4lcQ5qk z)B!KouU%_4`swK0`SS(&`5Ql|k|o_flxPqwCv*%9W)YCB$6&8d-#XuAW@*we` zOQJ9ku54{!kTC50x@l@X!~t}AK3%|<^1M;DDmwZ3?!LNuT|Jm2_i1c`?HwIz_wR4+ zckcl)N5d*r;fXUnf}Bo{BUcLo@me-``T8|b-6T zfhWiGVO)HCKrXI_3D#>v=zrOwP=b@X+aVALPc)VcA#meHALek$s3G=7ArRVu$IT&h z4M#g>+h#@<9tI5oM`>LG%Ag+*v`T)ewW+e)gqb2%k5e<6_lwc1Z>2m6eDUljdu@P3 z*b=p&FMh!`$)eJ04T@_9WQm%Zx~HcHbgf*VU@;mWxa=ZT;V8!u+KU%mel(wxta;S` z&IszG6tN8e=^CboojVc8!n~v@F$DSZt!qjB{rzljJbZizA9ZptC6Ml z*MZ#OEw1{3UmO?>u}x;beAxzR3UcL8IDGpPhT$+gZ`M zY)jM;c}aeP(As2UvQIt$kyj@!D~4?+SqAtJW|P`lTJi%O^sPZkVvEdB;o+3HX3*XQ z>^zK~ALN2dMxqu?^ZrV8Z%%*Zl%6#|g`?P*C=fjO1szGhef(mz+dMV9oFAa?;Pmx~ zq-b2Za)m8ydlicYO^1SFBD+Z>4TxfsefRDicwEG)`ArZ7jo3G}-w@<3iv>kRqQ6sa z8qkQ(4d&}*2JA0Vu=}~pr+ZN|3cr80yE=w)9-f~jB1}A`W4B#7wez=`L3 zY9K8G^rD-a6|oay*wt$$#;R~ZPG=Lc~8J}?0cV_e>Z;= z^H$@!tX}{XI8^uf*G5)XUP+@wQoBI|f%(>h=YFUT*)dyNTT#@6_3opdG)b}42xGE^ zmk1}PUQc^w+_;t|VPm=tIUtVWN<&pf$LTZ#$X$71Oy*(&PaP{yXL(ZVh6as>zTVzm zpLtK;Fl5tIUvDA+rsrK&*zpY9%%eDI)bbdrWUB{8~ z1RJFLa6Wx(@fK!3?Q~EKqq#bwMSXjs+QQs?{LLj!L%4DFyz#QzC^&Xi-;Bkp?WHCA zfa$$pYTPKYaErqCKaK5EN6N7y7rdNy0hv}C0Q~O+h=K)4jJ<~>5jLtgi2hF(B5oTL zz}S^a#St_DGj)nQo=ZKrM1C_2+H38Pd#`2iefM1Td&P}|Pmwja-B^@|XR$qo6EvhO z{kIb`oC~P)hzLfb2HFiB9UBQ|g{afRfA5Q3`IaY#RNl|Gbb~Z+o=ULPy9RBGonqHr zC8bx*qrpz46Q|$+xpCvho5;wWqA_^ksXd*eSgMn}P@yES*vb|I3(9@%`t=Wac?aX@ z7wzq;R#e|+y3F%T&P;gU8$M31$ zMgDG3h(~dPJUma2_0@ofxEuWZqA413{tQ<+Ifv3;u1q#qe#Ry6uma?)b9HqEJ$}Dc zyS%(Sdwct?u``lsiHV7C-#$i-K@8^p_rVm)Nq_tAEXyxn{tt+>9B?2JrU($}OoH+e`rS>yw!pD)#P1-=S@pEF zvoxXeb8~>3q-#EY{8(34cfN}AF}x0$c@az{!p}=Dx|NSUta<+%!kQSfH7NC-&*rNH zL7j(=qlg7g;AdH%a&eDD>jhM89&qO$ch?GgZnZrV%F85*`D*{bTjO)>K?c8{tGW`V_^k(fWHQASZsz#>}8v#4`=dm1y3TW<4rAQYF*DsGMkIl0|*#zd2kCz z=)Ljos}ioocaXr=#lKtj<1Ea}87WlA8IbQ<*{IHGo2=n3$M{NK^k+JCz8O zOtQ&Jfo@l9ZDli85V2VE&vmDwtXj@b)^vk?siR09Ez5@X)DQ5Y*h~x#Ck5A}2bMy> zjxd}!rxC+xZfl#Loh4wN95-DUp@XaOCyB#$y%Nz3o((l?rR`>~q4L?!1gB?G!p!8l z;!Su8Gdchb#J4}X?F(~$$LcwzzwF;jUuiz^RBw%nS<-X6r(`HcxU9z;RWMr)qLbOc zcw12^coh^B)Nb>9XW(>q*$aKw#BZ~kaz@<4v`@_SZwA6E3yR{Tkf7rhbE6`-`4bIQrp!{HjTX_=X8 zVX1$%qhBPJOMA`Eec}z0D%E^rE{q`0y0A6ZE%H0%*|TR|fyUtC=f|y7TbP1uFW{AK zY?tElO0wB~MN=>)T}EwVL#4odt#c{w@~C5_THN*AbUIpEE8!HtqNnJ*9`;2W&cTh= z4oBrb-Qwj()wyAm=isCZFPo;c1LoG&N>~L11a=b8E^Y2GU6@&rMn-kj*pPo>{bsf= zz8ZIe=IEMO!f>FlJs1uW_ohd;Z!+8m6ft`&Gd*2)w%D+;9IEHJgc*t2JNrN6yX=m) zQz)p>PIK1FrgG|sY4PEdmF47F%!Y+S)q}FncJLVc7hW2m(w)3`azN8s=K-nnxv_P0 z0_(cnu0VIv_?v<~r{28rn4?%G`T`xd3B6sl>m-LdRDe-B(m#l#FRrXixM&bSYJFAU zAgJsvZi;BRw!&H4y^rmOemgZ33ig0WzaIqkL~gfX?(I1QqCBa}E)e6!-pj^7r)OlO z0_GmpVijY|&BaAnwQ!MO@!w|}5VKg}Zs8M@;7FP-=1~!50 zo@Q??cBA(}{MPH2Z_R~C?}B}YIymIhJTb=p3CQ#!lD~m-dO5+FC3>r7Ck`7T`keZv zym?B^P3h}Bk145WYRdu&z!vnOPqH4VfBtOCm>FQQxa_6fI^5XUxW(T6Xn2yDy~1`^ zl*yuA&>4Uq_84#4{}GWWN7iIbJBQtMoQgBMIcV{?eb``(g~pB^QX_3r&n$F(CwJU0 zvp$bHxXB8U9IW!q6;}k&b-qzO)w+bMF`y<$1>Ld)sz%1UmGpkINI4}Zi_qaaozpAYP8Er@6*+{%I_HS_DZmiS{{j}= zZ+Q9RJkUf|7hiE$6C3tF2wqgrPX!Wv#&lE#ARuc;0G63`Dw!ee{;tEt- z*NEmLi|$DokzYgs5O|UO z!G2 Date: Wed, 10 Dec 2014 19:50:21 +0800 Subject: [PATCH 04/10] 0.2.0 --- CHANGELOG | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ CHANGES | 39 --------------------------------------- 2 files changed, 48 insertions(+), 39 deletions(-) create mode 100644 CHANGELOG delete mode 100644 CHANGES diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 000000000..262cc4dbb --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,48 @@ + +Changes with emqtt 0.2.0 07 Dec 2014 + +*) rewrite the project, integrate with esockd, mochiweb + +*) support MQTT 3.1.1 + +*) support HTTP to publish message + +Changes with emqtt 0.1.5 05 Jan 2012 + +*) Bugfix: remove QOS_1 match when handle PUBREL request + +*) Bugfix: reverse word in emqtt_topic:words/1 function + + +Changes with emqtt 0.1.4 04 Jan 2012 + +*) Bugfix: fix "mosquitto_sub -q 2 ......" bug + +*) Bugfix: fix keep alive bug + +Changes with emqtt 0.1.3 04 Jan 2012 + +*) Feature: support QOS2 PUBREC, PUBREL,PUBCOMP messages + +*) Bugfix: fix emqtt_frame to encode/decoe PUBREC/PUBREL messages + + +Changes with emqtt 0.1.2 27 Dec 2012 + +*) Feature: release support like riak + +*) Bugfix: use ?INFO/?ERROR to print log in tcp_listener.erl + + +Changes with emqtt 0.1.1 24 Dec 2012 + +*) Feature: use rebar to generate release + +*) Feature: support retained messages + +*) Bugfix: send will msg when network error + +Changes with emqtt 0.1.0 21 Dec 2012 + +*) The first public release. + diff --git a/CHANGES b/CHANGES deleted file mode 100644 index a04c03cc1..000000000 --- a/CHANGES +++ /dev/null @@ -1,39 +0,0 @@ -Changes with emqtt 0.1.5 05 Jan 2012 - - *) Bugfix: remove QOS_1 match when handle PUBREL request - - *) Bugfix: reverse word in emqtt_topic:words/1 function - - -Changes with emqtt 0.1.4 04 Jan 2012 - - *) Bugfix: fix "mosquitto_sub -q 2 ......" bug - - *) Bugfix: fix keep alive bug - -Changes with emqtt 0.1.3 04 Jan 2012 - - *) Feature: support QOS2 PUBREC, PUBREL,PUBCOMP messages - - *) Bugfix: fix emqtt_frame to encode/decoe PUBREC/PUBREL messages - - -Changes with emqtt 0.1.2 27 Dec 2012 - - *) Feature: release support like riak - - *) Bugfix: use ?INFO/?ERROR to print log in tcp_listener.erl - - -Changes with emqtt 0.1.1 24 Dec 2012 - - *) Feature: use rebar to generate release - - *) Feature: support retained messages - - *) Bugfix: send will msg when network error - -Changes with emqtt 0.1.0 21 Dec 2012 - - *) The first public release. - From 91c8e624c79ccdfb71e50b1a1cbd69e1f32d17de Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Wed, 10 Dec 2014 20:12:35 +0800 Subject: [PATCH 05/10] changelog --- CHANGELOG | 48 -------------------------------------------- CHANGELOG.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 48 deletions(-) delete mode 100644 CHANGELOG create mode 100644 CHANGELOG.md diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 262cc4dbb..000000000 --- a/CHANGELOG +++ /dev/null @@ -1,48 +0,0 @@ - -Changes with emqtt 0.2.0 07 Dec 2014 - -*) rewrite the project, integrate with esockd, mochiweb - -*) support MQTT 3.1.1 - -*) support HTTP to publish message - -Changes with emqtt 0.1.5 05 Jan 2012 - -*) Bugfix: remove QOS_1 match when handle PUBREL request - -*) Bugfix: reverse word in emqtt_topic:words/1 function - - -Changes with emqtt 0.1.4 04 Jan 2012 - -*) Bugfix: fix "mosquitto_sub -q 2 ......" bug - -*) Bugfix: fix keep alive bug - -Changes with emqtt 0.1.3 04 Jan 2012 - -*) Feature: support QOS2 PUBREC, PUBREL,PUBCOMP messages - -*) Bugfix: fix emqtt_frame to encode/decoe PUBREC/PUBREL messages - - -Changes with emqtt 0.1.2 27 Dec 2012 - -*) Feature: release support like riak - -*) Bugfix: use ?INFO/?ERROR to print log in tcp_listener.erl - - -Changes with emqtt 0.1.1 24 Dec 2012 - -*) Feature: use rebar to generate release - -*) Feature: support retained messages - -*) Bugfix: send will msg when network error - -Changes with emqtt 0.1.0 21 Dec 2012 - -*) The first public release. - diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..d2607c88e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,56 @@ +eMQTT ChangeLog +================== + +0.2.0 (2014-12-07) +------------------- + +rewrite the project, integrate with esockd, mochiweb + +support MQTT 3.1.1 + +support HTTP to publish message + +0.1.5 (2013-01-05) +------------------- + +Bugfix: remove QOS_1 match when handle PUBREL request + +Bugfix: reverse word in emqtt_topic:words/1 function + +0.1.4 (2013-01-04) +------------------- + +Bugfix: fix "mosquitto_sub -q 2 ......" bug + +Bugfix: fix keep alive bug + +0.1.3 (2012-01-04) +------------------- + +Feature: support QOS2 PUBREC, PUBREL,PUBCOMP messages + +Bugfix: fix emqtt_frame to encode/decoe PUBREC/PUBREL messages + + +0.1.2 (2012-12-27) +------------------- + +Feature: release support like riak + +Bugfix: use ?INFO/?ERROR to print log in tcp_listener.erl + + +0.1.1 (2012-09-24) +------------------- + +Feature: use rebar to generate release + +Feature: support retained messages + +Bugfix: send will msg when network error + +0.1.0 (2012-09-21) +------------------- + +The first public release. + From 2174e4633c47208d1cb49531ae6bfc5c5fe1e783 Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Wed, 10 Dec 2014 20:30:24 +0800 Subject: [PATCH 06/10] make dist --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4eb7d71b7..cb0143484 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ eMQTT requires Erlang R17+. $ cd emqtt - $ make && make generate + $ make && make dist $ cd rel/emqtt From 257646352361b5b9fe6017529e62e74c8fa8e129 Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Wed, 10 Dec 2014 20:32:14 +0800 Subject: [PATCH 07/10] admin, config --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cb0143484..020d0648e 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,14 @@ eMQTT requires Erlang R17+. ``` +## Configuration + +...... + +## Admin and Cluster + +...... + ## HTTP API eMQTT support http to publish message. @@ -70,7 +78,6 @@ message | Text Message The MIT License (MIT) ## Author -===== feng at slimchat.io From 2d6afe7ff3951e4433f1dd236e113f61dfcf0e96 Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Wed, 10 Dec 2014 21:27:07 +0800 Subject: [PATCH 08/10] eMQTT --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 020d0648e..de4686df3 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ eMQTT is a scalable, fault-tolerant and extensible mqtt broker written in Erlang/OTP. +eMQTT support MQTT V3.1 Protocol Specification. + eMQTT requires Erlang R17+. ## Startup in Five Minutes From 29a8a0f28370d7e6803b031d44d29ff1e5f9fa5e Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Thu, 11 Dec 2014 15:50:18 +0800 Subject: [PATCH 09/10] move 'process_request' to emqtt_protocol --- apps/emqtt/include/emqtt_frame.hrl | 17 +++ apps/emqtt/src/emqtt_client.erl | 152 --------------------------- apps/emqtt/src/emqtt_protocol.erl | 162 +++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 152 deletions(-) diff --git a/apps/emqtt/include/emqtt_frame.hrl b/apps/emqtt/include/emqtt_frame.hrl index e00191261..1aca3243c 100644 --- a/apps/emqtt/include/emqtt_frame.hrl +++ b/apps/emqtt/include/emqtt_frame.hrl @@ -23,6 +23,8 @@ -define(MQTT_PROTO_MAJOR, 3). -define(MQTT_PROTO_MINOR, 1). +-define(CLIENT_ID_MAXLEN, 23). + %% frame types -define(CONNECT, 1). @@ -49,6 +51,21 @@ -define(CONNACK_CREDENTIALS, 4). %% bad user name or password -define(CONNACK_AUTH, 5). %% not authorized +-record(state, {socket, + conn_name, + await_recv, + connection_state, + conserve, + parse_state, + message_id, + client_id, + clean_sess, + will_msg, + keep_alive, + awaiting_ack, + subtopics, + awaiting_rel}). + -record(mqtt_frame, {fixed, variable, diff --git a/apps/emqtt/src/emqtt_client.erl b/apps/emqtt/src/emqtt_client.erl index daa322fa7..500c66d6b 100644 --- a/apps/emqtt/src/emqtt_client.erl +++ b/apps/emqtt/src/emqtt_client.erl @@ -43,24 +43,6 @@ -include("emqtt_frame.hrl"). --define(CLIENT_ID_MAXLEN, 23). - --record(state, {socket, - conn_name, - await_recv, - connection_state, - conserve, - parse_state, - message_id, - client_id, - clean_sess, - will_msg, - keep_alive, - awaiting_ack, - subtopics, - awaiting_rel}). - - -define(FRAME_TYPE(Frame, Type), Frame = #mqtt_frame{ fixed = #mqtt_frame_fixed{ type = Type }}). @@ -233,140 +215,6 @@ process_frame(Frame = #mqtt_frame{fixed = #mqtt_frame_fixed{type = Type}}, {err, Reason, State} end. -process_request(?CONNECT, - #mqtt_frame{ variable = #mqtt_frame_connect{ - username = Username, - password = Password, - proto_ver = ProtoVersion, - clean_sess = CleanSess, - keep_alive = AlivePeriod, - client_id = ClientId } = Var}, #state{socket = Sock} = State) -> - {ReturnCode, State1} = - case {lists:member(ProtoVersion, proplists:get_keys(?PROTOCOL_NAMES)), - valid_client_id(ClientId)} of - {false, _} -> - {?CONNACK_PROTO_VER, State}; - {_, false} -> - {?CONNACK_INVALID_ID, State}; - _ -> - case emqtt_auth:check(Username, Password) of - false -> - ?ERROR_MSG("MQTT login failed - no credentials"), - {?CONNACK_CREDENTIALS, State}; - true -> - ?INFO("connect from clientid: ~p, ~p", [ClientId, AlivePeriod]), - emqtt_cm:create(ClientId, self()), - KeepAlive = emqtt_keep_alive:new(AlivePeriod*1500, keep_alive_timeout), - {?CONNACK_ACCEPT, - State #state{ will_msg = make_will_msg(Var), - client_id = ClientId, - keep_alive = KeepAlive}} - end - end, - ?INFO("recv conn...:~p", [ReturnCode]), - send_frame(Sock, #mqtt_frame{ fixed = #mqtt_frame_fixed{ type = ?CONNACK}, - variable = #mqtt_frame_connack{ - return_code = ReturnCode }}), - {ok, State1}; - -process_request(?PUBLISH, Frame=#mqtt_frame{ - fixed = #mqtt_frame_fixed{qos = ?QOS_0}}, State) -> - emqtt_pubsub:publish(make_msg(Frame)), - {ok, State}; - -process_request(?PUBLISH, - Frame=#mqtt_frame{ - fixed = #mqtt_frame_fixed{qos = ?QOS_1}, - variable = #mqtt_frame_publish{message_id = MsgId}}, - State=#state{socket=Sock}) -> - emqtt_pubsub:publish(make_msg(Frame)), - send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{ type = ?PUBACK }, - variable = #mqtt_frame_publish{ message_id = MsgId}}), - {ok, State}; - -process_request(?PUBLISH, - Frame=#mqtt_frame{ - fixed = #mqtt_frame_fixed{qos = ?QOS_2}, - variable = #mqtt_frame_publish{message_id = MsgId}}, - State=#state{socket=Sock}) -> - emqtt_pubsub:publish(make_msg(Frame)), - put({msg, MsgId}, pubrec), - send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{type = ?PUBREC}, - variable = #mqtt_frame_publish{ message_id = MsgId}}), - - {ok, State}; - -process_request(?PUBACK, #mqtt_frame{}, State) -> - %TODO: fixme later - {ok, State}; - -process_request(?PUBREC, #mqtt_frame{ - variable = #mqtt_frame_publish{message_id = MsgId}}, - State=#state{socket=Sock}) -> - %TODO: fixme later - send_frame(Sock, - #mqtt_frame{fixed = #mqtt_frame_fixed{ type = ?PUBREL}, - variable = #mqtt_frame_publish{ message_id = MsgId}}), - {ok, State}; - -process_request(?PUBREL, - #mqtt_frame{ - variable = #mqtt_frame_publish{message_id = MsgId}}, - State=#state{socket=Sock}) -> - erase({msg, MsgId}), - send_frame(Sock, - #mqtt_frame{fixed = #mqtt_frame_fixed{ type = ?PUBCOMP}, - variable = #mqtt_frame_publish{ message_id = MsgId}}), - {ok, State}; - -process_request(?PUBCOMP, #mqtt_frame{ - variable = #mqtt_frame_publish{message_id = _MsgId}}, State) -> - %TODO: fixme later - {ok, State}; - -process_request(?SUBSCRIBE, - #mqtt_frame{ - variable = #mqtt_frame_subscribe{message_id = MessageId, - topic_table = Topics}, - payload = undefined}, - #state{socket=Sock} = State) -> - - [emqtt_pubsub:subscribe({Name, Qos}, self()) || - #mqtt_topic{name=Name, qos=Qos} <- Topics], - - GrantedQos = [Qos || #mqtt_topic{qos=Qos} <- Topics], - - send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{type = ?SUBACK}, - variable = #mqtt_frame_suback{ - message_id = MessageId, - qos_table = GrantedQos}}), - - {ok, State}; - -process_request(?UNSUBSCRIBE, - #mqtt_frame{ - variable = #mqtt_frame_subscribe{message_id = MessageId, - topic_table = Topics }, - payload = undefined}, #state{socket = Sock, client_id = ClientId} = State) -> - - - [emqtt_pubsub:unsubscribe(Name, self()) || #mqtt_topic{name=Name} <- Topics], - - send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{type = ?UNSUBACK }, - variable = #mqtt_frame_suback{message_id = MessageId }}), - - {ok, State}; - -process_request(?PINGREQ, #mqtt_frame{}, #state{socket=Sock, keep_alive=KeepAlive}=State) -> - %Keep alive timer - KeepAlive1 = emqtt_keep_alive:reset(KeepAlive), - send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{ type = ?PINGRESP }}), - {ok, State#state{keep_alive=KeepAlive1}}; - -process_request(?DISCONNECT, #mqtt_frame{}, State=#state{client_id=ClientId}) -> - ?INFO("~s disconnected", [ClientId]), - {stop, State}. - next_msg_id(State = #state{ message_id = 16#ffff }) -> State #state{ message_id = 1 }; next_msg_id(State = #state{ message_id = MsgId }) -> diff --git a/apps/emqtt/src/emqtt_protocol.erl b/apps/emqtt/src/emqtt_protocol.erl index 468b70a22..66af58d4f 100644 --- a/apps/emqtt/src/emqtt_protocol.erl +++ b/apps/emqtt/src/emqtt_protocol.erl @@ -1,5 +1,167 @@ +%%----------------------------------------------------------------------------- +%% Copyright (c) 2014, Feng Lee +%% +%% 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. +%%------------------------------------------------------------------------------ -module(emqtt_protocol). +-include("emqtt.hrl"). + +-include("emqtt_log.hrl"). + -include("emqtt_frame.hrl"). +-export([process_request/3]). + +process_request(?CONNECT, + #mqtt_frame{ variable = #mqtt_frame_connect{ + username = Username, + password = Password, + proto_ver = ProtoVersion, + clean_sess = CleanSess, + keep_alive = AlivePeriod, + client_id = ClientId } = Var}, #state{socket = Sock} = State) -> + {ReturnCode, State1} = + case {lists:member(ProtoVersion, proplists:get_keys(?PROTOCOL_NAMES)), + valid_client_id(ClientId)} of + {false, _} -> + {?CONNACK_PROTO_VER, State}; + {_, false} -> + {?CONNACK_INVALID_ID, State}; + _ -> + case emqtt_auth:check(Username, Password) of + false -> + ?ERROR_MSG("MQTT login failed - no credentials"), + {?CONNACK_CREDENTIALS, State}; + true -> + ?INFO("connect from clientid: ~p, ~p", [ClientId, AlivePeriod]), + emqtt_cm:create(ClientId, self()), + KeepAlive = emqtt_keep_alive:new(AlivePeriod*1500, keep_alive_timeout), + {?CONNACK_ACCEPT, + State #state{ will_msg = make_will_msg(Var), + client_id = ClientId, + keep_alive = KeepAlive}} + end + end, + ?INFO("recv conn...:~p", [ReturnCode]), + send_frame(Sock, #mqtt_frame{ fixed = #mqtt_frame_fixed{ type = ?CONNACK}, + variable = #mqtt_frame_connack{ + return_code = ReturnCode }}), + {ok, State1}; + +process_request(?PUBLISH, Frame=#mqtt_frame{ + fixed = #mqtt_frame_fixed{qos = ?QOS_0}}, State) -> + emqtt_pubsub:publish(make_msg(Frame)), + {ok, State}; + +process_request(?PUBLISH, + Frame=#mqtt_frame{ + fixed = #mqtt_frame_fixed{qos = ?QOS_1}, + variable = #mqtt_frame_publish{message_id = MsgId}}, + State=#state{socket=Sock}) -> + emqtt_pubsub:publish(make_msg(Frame)), + send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{ type = ?PUBACK }, + variable = #mqtt_frame_publish{ message_id = MsgId}}), + {ok, State}; + +process_request(?PUBLISH, + Frame=#mqtt_frame{ + fixed = #mqtt_frame_fixed{qos = ?QOS_2}, + variable = #mqtt_frame_publish{message_id = MsgId}}, + State=#state{socket=Sock}) -> + emqtt_pubsub:publish(make_msg(Frame)), + put({msg, MsgId}, pubrec), + send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{type = ?PUBREC}, + variable = #mqtt_frame_publish{ message_id = MsgId}}), + + {ok, State}; + +process_request(?PUBACK, #mqtt_frame{}, State) -> + %TODO: fixme later + {ok, State}; + +process_request(?PUBREC, #mqtt_frame{ + variable = #mqtt_frame_publish{message_id = MsgId}}, + State=#state{socket=Sock}) -> + %TODO: fixme later + send_frame(Sock, + #mqtt_frame{fixed = #mqtt_frame_fixed{ type = ?PUBREL}, + variable = #mqtt_frame_publish{ message_id = MsgId}}), + {ok, State}; + +process_request(?PUBREL, + #mqtt_frame{ + variable = #mqtt_frame_publish{message_id = MsgId}}, + State=#state{socket=Sock}) -> + erase({msg, MsgId}), + send_frame(Sock, + #mqtt_frame{fixed = #mqtt_frame_fixed{ type = ?PUBCOMP}, + variable = #mqtt_frame_publish{ message_id = MsgId}}), + {ok, State}; + +process_request(?PUBCOMP, #mqtt_frame{ + variable = #mqtt_frame_publish{message_id = _MsgId}}, State) -> + %TODO: fixme later + {ok, State}; + +process_request(?SUBSCRIBE, + #mqtt_frame{ + variable = #mqtt_frame_subscribe{message_id = MessageId, + topic_table = Topics}, + payload = undefined}, + #state{socket=Sock} = State) -> + + [emqtt_pubsub:subscribe({Name, Qos}, self()) || + #mqtt_topic{name=Name, qos=Qos} <- Topics], + + GrantedQos = [Qos || #mqtt_topic{qos=Qos} <- Topics], + + send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{type = ?SUBACK}, + variable = #mqtt_frame_suback{ + message_id = MessageId, + qos_table = GrantedQos}}), + + {ok, State}; + +process_request(?UNSUBSCRIBE, + #mqtt_frame{ + variable = #mqtt_frame_subscribe{message_id = MessageId, + topic_table = Topics }, + payload = undefined}, #state{socket = Sock, client_id = ClientId} = State) -> + + + [emqtt_pubsub:unsubscribe(Name, self()) || #mqtt_topic{name=Name} <- Topics], + + send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{type = ?UNSUBACK }, + variable = #mqtt_frame_suback{message_id = MessageId }}), + + {ok, State}; + +process_request(?PINGREQ, #mqtt_frame{}, #state{socket=Sock, keep_alive=KeepAlive}=State) -> + %Keep alive timer + KeepAlive1 = emqtt_keep_alive:reset(KeepAlive), + send_frame(Sock, #mqtt_frame{fixed = #mqtt_frame_fixed{ type = ?PINGRESP }}), + {ok, State#state{keep_alive=KeepAlive1}}; + +process_request(?DISCONNECT, #mqtt_frame{}, State=#state{client_id=ClientId}) -> + ?INFO("~s disconnected", [ClientId]), + {stop, State}. + + From 4a2b586ff9d544b3cb85fca0df6a36bd104da8ed Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Sun, 28 Dec 2014 21:27:08 +0800 Subject: [PATCH 10/10] fix clientId length --- apps/emqtt/include/emqtt_frame.hrl | 2 ++ apps/emqtt/src/emqtt_client.erl | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/emqtt/include/emqtt_frame.hrl b/apps/emqtt/include/emqtt_frame.hrl index e00191261..d51f3663b 100644 --- a/apps/emqtt/include/emqtt_frame.hrl +++ b/apps/emqtt/include/emqtt_frame.hrl @@ -18,6 +18,8 @@ %% Copyright (c) 2007-2012 VMware, Inc. All rights reserved. %% +-define(CLIENT_ID_MAXLEN, 1024). + -define(PROTOCOL_NAMES, [{3, <<"MQIsdp">>}, {4, <<"MQTT">>}]). -define(MQTT_PROTO_MAJOR, 3). diff --git a/apps/emqtt/src/emqtt_client.erl b/apps/emqtt/src/emqtt_client.erl index daa322fa7..da5dabfb0 100644 --- a/apps/emqtt/src/emqtt_client.erl +++ b/apps/emqtt/src/emqtt_client.erl @@ -43,8 +43,6 @@ -include("emqtt_frame.hrl"). --define(CLIENT_ID_MAXLEN, 23). - -record(state, {socket, conn_name, await_recv,