From 31bc0918737ccca440262a13cdb464e195e6968c Mon Sep 17 00:00:00 2001 From: Feng Lee Date: Sun, 6 May 2018 17:45:18 +0800 Subject: [PATCH] Implement MQTT Version 5.0 client --- docs/mqtt-v5.0.pdf | Bin 1707553 -> 2557522 bytes include/emqx_client.hrl | 37 -- include/emqx_mqtt.hrl | 265 ++++++++--- src/emqx_broker.erl | 2 +- src/emqx_client.erl | 794 ++++++++++++++++++++------------- src/emqx_client_sock.erl | 100 +---- src/emqx_connection.erl | 73 +-- src/emqx_mod_subscription.erl | 8 +- src/emqx_mqtt_properties.erl | 117 +++-- src/emqx_mqtt_rscode.erl | 115 ----- src/emqx_packet.erl | 68 ++- src/emqx_parser.erl | 442 +++++++++--------- src/emqx_protocol.erl | 84 ++-- src/emqx_reason_codes.erl | 110 +++++ src/emqx_router.erl | 2 +- src/emqx_serializer.erl | 356 ++++++++------- src/emqx_session.erl | 11 +- src/emqx_sm_sup.erl | 2 +- test/emqx_access_SUITE.erl | 10 +- test/emqx_protocol_SUITE.erl | 60 +-- test/emqx_serializer_SUITE.erl | 91 ++++ 21 files changed, 1510 insertions(+), 1237 deletions(-) delete mode 100644 include/emqx_client.hrl delete mode 100644 src/emqx_mqtt_rscode.erl create mode 100644 src/emqx_reason_codes.erl create mode 100644 test/emqx_serializer_SUITE.erl diff --git a/docs/mqtt-v5.0.pdf b/docs/mqtt-v5.0.pdf index 8f8690e08c98d7cc8ea096c4327f8ed96b22a288..1fa8883d0517edaf5e2df9010b9601a223a4d1e4 100644 GIT binary patch delta 855995 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 |*@y;w9(WD%voL#!L4 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 z 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

P`|91cYwY|=E)P)J|2;)n>1~NM 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 HyI=i3@)qP% delta 62 zcmV~$xfOy?006MZp#m!RB^}!_21QCn_zgQSi4&3hj}V<<+eKoD)Wg$DCRcd-_$pOu PjaH{O7)@rsYgx-1lcW error_logger:info_msg(Msg); - info -> error_logger:info_msg(Msg); - warning -> error_logger:warning_msg(Msg); - error -> error_logger:error_msg(Msg); - critical -> error_logger:error_msg(Msg) - end)). --define(LOG(Level, Format, Args), - (case Level of - debug -> error_logger:info_msg(Format, Args); - info -> error_logger:info_msg(Format, Args); - warning -> error_logger:warning_msg(Format, Args); - error -> error_logger:error_msg(Format, Args); - critical -> error_logger:error_msg(Format, Args) - end)). - --endif. - diff --git a/include/emqx_mqtt.hrl b/include/emqx_mqtt.hrl index fb7201f02..793c9d501 100644 --- a/include/emqx_mqtt.hrl +++ b/include/emqx_mqtt.hrl @@ -22,7 +22,7 @@ {backlog, 512}, {nodelay, true}]). %%-------------------------------------------------------------------- -%% MQTT Protocol Version and Levels +%% MQTT Protocol Version and Names %%-------------------------------------------------------------------- -define(MQTT_PROTO_V3, 3). @@ -34,10 +34,10 @@ {?MQTT_PROTO_V4, <<"MQTT">>}, {?MQTT_PROTO_V5, <<"MQTT">>}]). --type(mqtt_vsn() :: ?MQTT_PROTO_V3 | ?MQTT_PROTO_V4 | ?MQTT_PROTO_V5). +-type(mqtt_version() :: ?MQTT_PROTO_V3 | ?MQTT_PROTO_V4 | ?MQTT_PROTO_V5). %%-------------------------------------------------------------------- -%% MQTT QoS Level +%% MQTT QoS Levels %%-------------------------------------------------------------------- -define(QOS_0, 0). %% At most once @@ -71,8 +71,13 @@ end) end). +-define(IS_QOS_NAME(I), + (I =:= qos0; I =:= at_most_once; + I =:= qos1; I =:= at_least_once; + I =:= qos2; I =:= exactly_once)). + %%-------------------------------------------------------------------- -%% Max ClientId Length. Why 1024? +%% Maximum ClientId Length. Why 1024? %%-------------------------------------------------------------------- -define(MAX_CLIENTID_LEN, 1024). @@ -87,8 +92,8 @@ username :: binary() | undefined, peername :: {inet:ip_address(), inet:port_number()}, clean_sess :: boolean(), - proto_ver :: 3 | 4, - keepalive = 0, + proto_ver :: mqtt_version(), + keepalive = 0 :: non_neg_integer(), will_topic :: undefined | binary(), mountpoint :: undefined | binary(), connected_at :: erlang:timestamp(), @@ -119,39 +124,76 @@ -define(AUTH, 15). %% Authentication exchange -define(TYPE_NAMES, [ - 'CONNECT', - 'CONNACK', - 'PUBLISH', - 'PUBACK', - 'PUBREC', - 'PUBREL', - 'PUBCOMP', - 'SUBSCRIBE', - 'SUBACK', - 'UNSUBSCRIBE', - 'UNSUBACK', - 'PINGREQ', - 'PINGRESP', - 'DISCONNECT', - 'AUTH']). + 'CONNECT', + 'CONNACK', + 'PUBLISH', + 'PUBACK', + 'PUBREC', + 'PUBREL', + 'PUBCOMP', + 'SUBSCRIBE', + 'SUBACK', + 'UNSUBSCRIBE', + 'UNSUBACK', + 'PINGREQ', + 'PINGRESP', + 'DISCONNECT', + 'AUTH']). -type(mqtt_packet_type() :: ?RESERVED..?AUTH). %%-------------------------------------------------------------------- -%% MQTT Connect Return Codes +%% MQTT Reason Codes %%-------------------------------------------------------------------- --define(CONNACK_ACCEPT, 0). %% Connection accepted --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_SERVER, 3). %% Server unavailable --define(CONNACK_CREDENTIALS, 4). %% Username or password is malformed --define(CONNACK_AUTH, 5). %% Client is not authorized to connect - --type(mqtt_connack() :: ?CONNACK_ACCEPT..?CONNACK_AUTH). +-define(RC_SUCCESS, 16#00). +-define(RC_NORMAL_DISCONNECTION, 16#00). +-define(RC_GRANTED_QOS_0, 16#00). +-define(RC_GRANTED_QOS_1, 16#01). +-define(RC_GRANTED_QOS_2, 16#02). +-define(RC_DISCONNECT_WITH_WILL_MESSAGE, 16#04). +-define(RC_NO_MATCHING_SUBSCRIBERS, 16#10). +-define(RC_NO_SUBSCRIPTION_EXISTED, 16#11). +-define(RC_CONTINUE_AUTHENTICATION, 16#18). +-define(RC_RE_AUTHENTICATE, 16#19). +-define(RC_UNSPECIFIED_ERROR, 16#80). +-define(RC_MALFORMED_PACKET, 16#81). +-define(RC_PROTOCOL_ERROR, 16#82). +-define(RC_IMPLEMENTATION_SPECIFIC_ERROR, 16#83). +-define(RC_UNSUPPORTED_PROTOCOL_VERSION, 16#84). +-define(RC_CLIENT_IDENTIFIER_NOT_VALID, 16#85). +-define(RC_BAD_USER_NAME_OR_PASSWORD, 16#86). +-define(RC_NOT_AUTHORIZED, 16#87). +-define(RC_SERVER_UNAVAILABLE, 16#88). +-define(RC_SERVER_BUSY, 16#89). +-define(RC_BANNED, 16#8A). +-define(RC_SERVER_SHUTTING_DOWN, 16#8B). +-define(RC_BAD_AUTHENTICATION_METHOD, 16#8C). +-define(RC_KEEP_ALIVE_TIMEOUT, 16#8D). +-define(RC_SESSION_TAKEN_OVER, 16#8E). +-define(RC_TOPIC_FILTER_INVALID, 16#8F). +-define(RC_TOPIC_NAME_INVALID, 16#90). +-define(RC_PACKET_IDENTIFIER_IN_USE, 16#91). +-define(RC_PACKET_IDENTIFIER_NOT_FOUND, 16#92). +-define(RC_RECEIVE_MAXIMUM_EXCEEDED, 16#93). +-define(RC_TOPIC_ALIAS_INVALID, 16#94). +-define(RC_PACKET_TOO_LARGE, 16#95). +-define(RC_MESSAGE_RATE_TOO_HIGH, 16#96). +-define(RC_QUOTA_EXCEEDED, 16#97). +-define(RC_ADMINISTRATIVE_ACTION, 16#98). +-define(RC_PAYLOAD_FORMAT_INVALID, 16#99). +-define(RC_RETAIN_NOT_SUPPORTED, 16#9A). +-define(RC_QOS_NOT_SUPPORTED, 16#9B). +-define(RC_USE_ANOTHER_SERVER, 16#9C). +-define(RC_SERVER_MOVED, 16#9D). +-define(RC_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED, 16#9E). +-define(RC_CONNECTION_RATE_EXCEEDED, 16#9F). +-define(RC_MAXIMUM_CONNECT_TIME, 16#A0). +-define(RC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED, 16#A1). +-define(RC_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED, 16#A2). %%-------------------------------------------------------------------- -%% Max MQTT Packet Length +%% Maximum MQTT Packet Length %%-------------------------------------------------------------------- -define(MAX_PACKET_SIZE, 16#fffffff). @@ -184,44 +226,43 @@ -type(mqtt_username() :: binary() | undefined). --type(mqtt_packet_id() :: 1..16#ffff | undefined). +-type(mqtt_packet_id() :: 1..16#FFFF | undefined). --type(mqtt_reason_code() :: 1..16#ff | undefined). +-type(mqtt_reason_code() :: 0..16#FF | undefined). --type(mqtt_properties() :: undefined | map()). +-type(mqtt_properties() :: #{atom() => term()} | undefined). --type(mqtt_subopt() :: {qos, mqtt_qos()} - | {retain_handling, boolean()} - | {keep_retain, boolean()} - | {no_local, boolean()}). +%% nl: no local, rap: retain as publish, rh: retain handling +-record(mqtt_subopts, {rh = 0, rap = 0, nl = 0, qos = ?QOS_0}). + +-type(mqtt_subopts() :: #mqtt_subopts{}). -record(mqtt_packet_connect, - { client_id = <<>> :: mqtt_client_id(), - proto_ver = ?MQTT_PROTO_V4 :: mqtt_vsn(), - proto_name = <<"MQTT">> :: binary(), - will_retain = false :: boolean(), - will_qos = ?QOS_1 :: mqtt_qos(), - will_flag = false :: boolean(), - clean_sess = false :: boolean(), - clean_start = true :: boolean(), - keep_alive = 60 :: non_neg_integer(), - will_props = undefined :: undefined | map(), - will_topic = undefined :: undefined | binary(), - will_msg = undefined :: undefined | binary(), - username = undefined :: undefined | binary(), - password = undefined :: undefined | binary(), - is_bridge = false :: boolean(), - properties = undefined :: mqtt_properties() %% MQTT Version 5.0 + { proto_name = <<"MQTT">> :: binary(), + proto_ver = ?MQTT_PROTO_V4 :: mqtt_version(), + is_bridge = false :: boolean(), + clean_start = true :: boolean(), + will_flag = false :: boolean(), + will_qos = ?QOS_1 :: mqtt_qos(), + will_retain = false :: boolean(), + keepalive = 0 :: non_neg_integer(), + properties = undefined :: mqtt_properties(), + client_id = <<>> :: mqtt_client_id(), + will_props = undefined :: undefined | map(), + will_topic = undefined :: undefined | binary(), + will_payload = undefined :: undefined | binary(), + username = undefined :: undefined | binary(), + password = undefined :: undefined | binary() }). -record(mqtt_packet_connack, - { ack_flags = ?RESERVED :: 0 | 1, - reason_code :: mqtt_connack(), - properties :: map() + { ack_flags :: 0 | 1, + reason_code :: mqtt_reason_code(), + properties :: mqtt_properties() }). -record(mqtt_packet_publish, - { topic_name :: binary(), + { topic_name :: mqtt_topic(), packet_id :: mqtt_packet_id(), properties :: mqtt_properties() }). @@ -235,13 +276,7 @@ -record(mqtt_packet_subscribe, { packet_id :: mqtt_packet_id(), properties :: mqtt_properties(), - topic_filters :: list({binary(), mqtt_subopt()}) - }). - --record(mqtt_packet_unsubscribe, - { packet_id :: mqtt_packet_id(), - properties :: mqtt_properties(), - topics :: list(binary()) + topic_filters :: [{mqtt_topic(), mqtt_subopts()}] }). -record(mqtt_packet_suback, @@ -250,9 +285,15 @@ reason_codes :: list(mqtt_reason_code()) }). +-record(mqtt_packet_unsubscribe, + { packet_id :: mqtt_packet_id(), + properties :: mqtt_properties(), + topic_filters :: [mqtt_topic()] + }). + -record(mqtt_packet_unsuback, - { packet_id :: mqtt_packet_id(), - properties :: mqtt_properties(), + { packet_id :: mqtt_packet_id(), + properties :: mqtt_properties(), reason_codes :: list(mqtt_reason_code()) }). @@ -311,6 +352,19 @@ reason_code = ReasonCode, properties = Properties}}). +-define(AUTH_PACKET(), + #mqtt_packet{header = #mqtt_packet_header{type = ?AUTH}, + variable = #mqtt_packet_auth{reason_code = 0}}). + +-define(AUTH_PACKET(ReasonCode), + #mqtt_packet{header = #mqtt_packet_header{type = ?AUTH}, + variable = #mqtt_packet_auth{reason_code = ReasonCode}}). + +-define(AUTH_PACKET(ReasonCode, Properties), + #mqtt_packet{header = #mqtt_packet_header{type = ?AUTH}, + variable = #mqtt_packet_auth{reason_code = ReasonCode, + properties = Properties}}). + -define(PUBLISH_PACKET(Qos, PacketId), #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH, qos = Qos}, @@ -323,31 +377,64 @@ packet_id = PacketId}, payload = Payload}). +-define(PUBLISH_PACKET(Header, Topic, PacketId, Properties, Payload), + #mqtt_packet{header = Header = #mqtt_packet_header{type = ?PUBLISH}, + variable = #mqtt_packet_publish{topic_name = Topic, + packet_id = PacketId, + properties = Properties}, + payload = Payload}). + -define(PUBACK_PACKET(PacketId), #mqtt_packet{header = #mqtt_packet_header{type = ?PUBACK}, variable = #mqtt_packet_puback{packet_id = PacketId}}). --define(PUBACK_PACKET(Type, PacketId), - #mqtt_packet{header = #mqtt_packet_header{type = Type}, - variable = #mqtt_packet_puback{packet_id = PacketId}}). +-define(PUBACK_PACKET(PacketId, ReasonCode, Properties), + #mqtt_packet{header = #mqtt_packet_header{type = ?PUBACK}, + variable = #mqtt_packet_puback{packet_id = PacketId, + reason_code = ReasonCode, + properties = Properties}}). -define(PUBREC_PACKET(PacketId), #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREC}, variable = #mqtt_packet_puback{packet_id = PacketId}}). +-define(PUBREC_PACKET(PacketId, ReasonCode, Properties), + #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREC}, + variable = #mqtt_packet_puback{packet_id = PacketId, + reason_code = ReasonCode, + properties = Properties}}). + -define(PUBREL_PACKET(PacketId), #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREL, qos = ?QOS_1}, variable = #mqtt_packet_puback{packet_id = PacketId}}). +-define(PUBREL_PACKET(PacketId, ReasonCode, Properties), + #mqtt_packet{header = #mqtt_packet_header{type = ?PUBREL, qos = ?QOS_1}, + variable = #mqtt_packet_puback{packet_id = PacketId, + reason_code = ReasonCode, + properties = Properties}}). + -define(PUBCOMP_PACKET(PacketId), #mqtt_packet{header = #mqtt_packet_header{type = ?PUBCOMP}, variable = #mqtt_packet_puback{packet_id = PacketId}}). +-define(PUBCOMP_PACKET(PacketId, ReasonCode, Properties), + #mqtt_packet{header = #mqtt_packet_header{type = ?PUBCOMP}, + variable = #mqtt_packet_puback{packet_id = PacketId, + reason_code = ReasonCode, + properties = Properties}}). + -define(SUBSCRIBE_PACKET(PacketId, TopicFilters), #mqtt_packet{header = #mqtt_packet_header{type = ?SUBSCRIBE, qos = ?QOS_1}, variable = #mqtt_packet_subscribe{packet_id = PacketId, topic_filters = TopicFilters}}). +-define(SUBSCRIBE_PACKET(PacketId, Properties, TopicFilters), + #mqtt_packet{header = #mqtt_packet_header{type = ?SUBSCRIBE, qos = ?QOS_1}, + variable = #mqtt_packet_subscribe{packet_id = PacketId, + properties = Properties, + topic_filters = TopicFilters}}). + -define(SUBACK_PACKET(PacketId, ReasonCodes), #mqtt_packet{header = #mqtt_packet_header{type = ?SUBACK}, variable = #mqtt_packet_suback{packet_id = PacketId, @@ -358,14 +445,39 @@ variable = #mqtt_packet_suback{packet_id = PacketId, properties = Properties, reason_codes = ReasonCodes}}). --define(UNSUBSCRIBE_PACKET(PacketId, Topics), +-define(UNSUBSCRIBE_PACKET(PacketId, TopicFilters), #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBSCRIBE, qos = ?QOS_1}, - variable = #mqtt_packet_unsubscribe{packet_id = PacketId, - topics = Topics}}). + variable = #mqtt_packet_unsubscribe{packet_id = PacketId, + topic_filters = TopicFilters}}). + +-define(UNSUBSCRIBE_PACKET(PacketId, Properties, TopicFilters), + #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBSCRIBE, qos = ?QOS_1}, + variable = #mqtt_packet_unsubscribe{packet_id = PacketId, + properties = Properties, + topic_filters = TopicFilters}}). + -define(UNSUBACK_PACKET(PacketId), - #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBACK}, + #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBACK}, variable = #mqtt_packet_unsuback{packet_id = PacketId}}). +-define(UNSUBACK_PACKET(PacketId, Properties, ReasonCodes), + #mqtt_packet{header = #mqtt_packet_header{type = ?UNSUBACK}, + variable = #mqtt_packet_unsuback{packet_id = PacketId, + properties = Properties, + reason_codes = ReasonCodes}}). + +-define(DISCONNECT_PACKET(), + #mqtt_packet{header = #mqtt_packet_header{type = ?DISCONNECT}}). + +-define(DISCONNECT_PACKET(ReasonCode), + #mqtt_packet{header = #mqtt_packet_header{type = ?DISCONNECT}, + variable = #mqtt_packet_disconnect{reason_code = ReasonCode}}). + +-define(DISCONNECT_PACKET(ReasonCode, Properties), + #mqtt_packet{header = #mqtt_packet_header{type = ?DISCONNECT}, + variable = #mqtt_packet_disconnect{reason_code = ReasonCode, + properties = Properties}}). + -define(PACKET(Type), #mqtt_packet{header = #mqtt_packet_header{type = Type}}). @@ -406,6 +518,11 @@ -type(mqtt_message() :: #mqtt_message{}). +-define(WILL_MSG(Qos, Retain, Topic, Props, Payload), + #mqtt_message{qos = WillQos, retain = WillRetain, + topic = WillTopic, properties = Props, + payload = WillPayload}). + %%-------------------------------------------------------------------- %% MQTT Delivery %%-------------------------------------------------------------------- diff --git a/src/emqx_broker.erl b/src/emqx_broker.erl index e40f181cb..57db2defe 100644 --- a/src/emqx_broker.erl +++ b/src/emqx_broker.erl @@ -56,7 +56,7 @@ -spec(start_link(atom(), pos_integer()) -> {ok, pid()} | ignore | {error, term()}). start_link(Pool, Id) -> - gen_server:start_link(emqx_misc:proc_name(?MODULE, Id), + gen_server:start_link({local, emqx_misc:proc_name(?MODULE, Id)}, ?MODULE, [Pool, Id], [{hibernate_after, 2000}]). %%-------------------------------------------------------------------- diff --git a/src/emqx_client.erl b/src/emqx_client.erl index fbfb92997..ef640fe43 100644 --- a/src/emqx_client.erl +++ b/src/emqx_client.erl @@ -19,19 +19,23 @@ -behaviour(gen_statem). -include("emqx_mqtt.hrl"). --include("emqx_client.hrl"). -export([start_link/0, start_link/1]). --export([subscribe/2, subscribe/3, unsubscribe/2]). +-export([subscribe/2, subscribe/3, subscribe/4]). -export([publish/2, publish/3, publish/4, publish/5]). +-export([unsubscribe/2, unsubscribe/3]). -export([ping/1]). --export([disconnect/1, disconnect/2]). --export([puback/2, pubrec/2, pubrel/2, pubcomp/2]). +-export([disconnect/1, disconnect/2, disconnect/3]). +-export([puback/2, puback/3, puback/4]). +-export([pubrec/2, pubrec/3, pubrec/4]). +-export([pubrel/2, pubrel/3, pubrel/4]). +-export([pubcomp/2, pubcomp/3, pubcomp/4]). -export([subscriptions/1]). +-export([info/1]). -export([initialized/3, waiting_for_connack/3, connected/3]). --export([init/1, callback_mode/0, terminate/3, code_change/4]). +-export([init/1, callback_mode/0, handle_event/4, terminate/3, code_change/4]). -type(host() :: inet:ip_address() | inet:hostname()). @@ -43,6 +47,8 @@ | {tcp_opts, [gen_tcp:option()]} | {ssl, boolean()} | {ssl_opts, [ssl:ssl_option()]} + | {connect_timeout, pos_integer()} + | {bridge_mode, boolean()} | {client_id, iodata()} | {clean_start, boolean()} | {username, iodata()} @@ -55,12 +61,13 @@ | {will_payload, iodata()} | {will_retain, boolean()} | {will_qos, mqtt_qos() | mqtt_qos_name()} - | {connect_timeout, pos_integer()} + | {will_props, mqtt_properties()} + | {auto_ack, boolean()} | {ack_timeout, pos_integer()} | {force_ping, boolean()} - | {debug_mode, boolean()}). + | {properties, mqtt_properties()}). --export_type([option/0]). +-export_type([host/0, option/0]). -record(state, {name :: atom(), owner :: pid(), @@ -69,46 +76,69 @@ hosts :: [{host(), inet:port_number()}], socket :: inet:socket(), sock_opts :: [emqx_client_sock:option()], - receiver :: pid(), + connect_timeout :: pos_integer(), + bridge_mode :: boolean(), client_id :: binary(), clean_start :: boolean(), + session_present :: boolean(), username :: binary() | undefined, password :: binary() | undefined, - proto_ver :: mqtt_vsn(), + proto_ver :: mqtt_version(), proto_name :: iodata(), keepalive :: non_neg_integer(), keepalive_timer :: reference() | undefined, + expiry_interval :: pos_integer(), force_ping :: boolean(), will_flag :: boolean(), will_msg :: mqtt_message(), + properties :: mqtt_properties(), pending_calls :: list(), - subscribers :: list(), subscriptions :: map(), max_inflight :: infinity | pos_integer(), inflight :: emqx_inflight:inflight(), awaiting_rel :: map(), - properties :: list(), auto_ack :: boolean(), ack_timeout :: pos_integer(), ack_timer :: reference(), retry_interval :: pos_integer(), retry_timer :: reference(), - connect_timeout :: pos_integer(), last_packet_id :: mqtt_packet_id(), - debug_mode :: boolean()}). + parse_state :: emqx_parser:state()}). -record(call, {id, from, req, ts}). -type(client() :: pid() | atom()). --type(msgid() :: mqtt_packet_id()). +-type(topic() :: mqtt_topic()). --type(pubopt() :: {retain, boolean()} - | {qos, mqtt_qos()}). +-type(payload() :: iodata()). --type(subopt() :: mqtt_subopt()). +-type(packet_id() :: mqtt_packet_id()). --export_type([client/0, host/0, msgid/0, pubopt/0, subopt/0]). +-type(properties() :: mqtt_properties()). + +-type(qos() :: mqtt_qos_name() | mqtt_qos()). + +-type(pubopt() :: {retain, boolean()} | {qos, qos()}). + +-type(subopt() :: {rh, 0 | 1 | 2} + | {rap, boolean()} + | {nl, boolean()} + | {qos, qos()}). + +-type(reason_code() :: mqtt_reason_code()). + +-type(subscribe_ret() :: {ok, properties(), [reason_code()]} | {error, term()}). + +-export_type([client/0, topic/0, qos/0, properties/0, payload/0, + packet_id/0, pubopt/0, subopt/0, reason_code/0]). + +%% Default timeout +-define(DEFAULT_KEEPALIVE, 60000). +-define(DEFAULT_ACK_TIMEOUT, 30000). +-define(DEFAULT_CONNECT_TIMEOUT, 60000). + +-define(PROPERTY(Name, Val), #state{properties = #{Name := Val}}). %%-------------------------------------------------------------------- %% API @@ -121,6 +151,8 @@ start_link() -> start_link([]). start_link(Options) when is_map(Options) -> start_link(maps:to_list(Options)); start_link(Options) when is_list(Options) -> + ok = emqx_mqtt_properties:validate( + proplists:get_value(properties, Options, #{})), case start_client(with_owner(Options)) of {ok, Client} -> connect(Client); @@ -142,110 +174,183 @@ with_owner(Options) -> end. %% @private -%% @doc should be called with start_link --spec(connect(client()) -> {ok, client()} | {error, term()}). +-spec(connect(client()) -> {ok, client(), properties()} | {error, term()}). connect(Client) -> gen_statem:call(Client, connect, infinity). -%% @doc Publish QoS0 message to broker. --spec(publish(client(), iolist(), iodata()) -> ok | {error, term()}). -publish(Client, Topic, Payload) -> - publish(Client, #mqtt_message{topic = iolist_to_binary(Topic), +-spec(subscribe(client(), topic() | {topic(), qos() | [subopt()]}) + -> subscribe_ret()). +subscribe(Client, Topic) when is_binary(Topic) -> + subscribe(Client, {Topic, ?QOS_0}); +subscribe(Client, {Topic, QoS}) when is_binary(Topic), is_atom(QoS) -> + subscribe(Client, {Topic, ?QOS_I(QoS)}); +subscribe(Client, {Topic, QoS}) when is_binary(Topic), ?IS_QOS(QoS) -> + subscribe(Client, [{Topic, ?QOS_I(QoS)}]); +subscribe(Client, Topics) when is_list(Topics) -> + subscribe(Client, #{}, lists:map( + fun({Topic, QoS}) when is_binary(Topic), is_atom(QoS) -> + {Topic, [{qos, ?QOS_I(QoS)}]}; + ({Topic, QoS}) when is_binary(Topic), ?IS_QOS(QoS) -> + {Topic, [{qos, ?QOS_I(QoS)}]}; + ({Topic, Opts}) when is_binary(Topic), is_list(Opts) -> + {Topic, Opts} + end, Topics)). + +-spec(subscribe(client(), topic(), qos() | [subopt()]) -> + subscribe_ret(); + (client(), properties(), [{topic(), qos() | [subopt()]}]) -> + subscribe_ret()). +subscribe(Client, Topic, QoS) when is_binary(Topic), is_atom(QoS) -> + subscribe(Client, Topic, ?QOS_I(QoS)); +subscribe(Client, Topic, QoS) when is_binary(Topic), ?IS_QOS(QoS) -> + subscribe(Client, Topic, [{qos, QoS}]); +subscribe(Client, Topic, Opts) when is_binary(Topic), is_list(Opts) -> + subscribe(Client, #{}, [{Topic, Opts}]); +subscribe(Client, Properties, Topics) when is_map(Properties), is_list(Topics) -> + Topics1 = [{Topic, parse_subopt(Opts)} || {Topic, Opts} <- Topics], + gen_statem:call(Client, {subscribe, Properties, Topics1}). + +-spec(subscribe(client(), properties(), topic(), qos() | [subopt()]) + -> subscribe_ret()). +subscribe(Client, Properties, Topic, QoS) + when is_map(Properties), is_binary(Topic), is_atom(QoS) -> + subscribe(Client, Properties, Topic, ?QOS_I(QoS)); +subscribe(Client, Properties, Topic, QoS) + when is_map(Properties), is_binary(Topic), ?IS_QOS(QoS) -> + subscribe(Client, Properties, Topic, [{qos, QoS}]); +subscribe(Client, Properties, Topic, Opts) + when is_map(Properties), is_binary(Topic), is_list(Opts) -> + subscribe(Client, Properties, [{Topic, Opts}]). + +parse_subopt(Opts) -> + parse_subopt(Opts, #mqtt_subopts{}). + +parse_subopt([], Rec) -> + Rec; +parse_subopt([{rh, I} | Opts], Rec) when I >= 0, I =< 2 -> + parse_subopt(Opts, Rec#mqtt_subopts{rh = I}); +parse_subopt([{rap, true} | Opts], Rec) -> + parse_subopt(Opts, Rec#mqtt_subopts{rap =1}); +parse_subopt([{rap, false} | Opts], Rec) -> + parse_subopt(Opts, Rec#mqtt_subopts{rap = 0}); +parse_subopt([{nl, true} | Opts], Rec) -> + parse_subopt(Opts, Rec#mqtt_subopts{nl = 1}); +parse_subopt([{nl, false} | Opts], Rec) -> + parse_subopt(Opts, Rec#mqtt_subopts{nl = 0}); +parse_subopt([{qos, QoS} | Opts], Rec) -> + parse_subopt(Opts, Rec#mqtt_subopts{qos = ?QOS_I(QoS)}). + +-spec(publish(client(), topic(), payload()) -> ok | {error, term()}). +publish(Client, Topic, Payload) when is_binary(Topic) -> + publish(Client, #mqtt_message{topic = Topic, qos = ?QOS_0, payload = iolist_to_binary(Payload)}). -%% @doc Publish message to broker with qos, retain options. --spec(publish(client(), iolist(), iodata(), - mqtt_qos() | mqtt_qos_name() | [pubopt()]) - -> ok | {ok, msgid()} | {error, term()}). -publish(Client, Topic, Payload, QoS) when is_atom(QoS) -> - publish(Client, Topic, Payload, ?QOS_I(QoS)); -publish(Client, Topic, Payload, QoS) when ?IS_QOS(QoS) -> +-spec(publish(client(), topic(), payload(), qos() | [pubopt()]) + -> ok | {ok, packet_id()} | {error, term()}). +publish(Client, Topic, Payload, QoS) when is_binary(Topic), is_atom(QoS) -> + publish(Client, Topic, Payload, [{qos, ?QOS_I(QoS)}]); +publish(Client, Topic, Payload, QoS) when is_binary(Topic), ?IS_QOS(QoS) -> publish(Client, Topic, Payload, [{qos, QoS}]); -publish(Client, Topic, Payload, Options) when is_list(Options) -> - publish(Client, Topic, [], Payload, Options). -publish(Client, Topic, Properties, Payload, Options) -> +publish(Client, Topic, Payload, Opts) when is_binary(Topic), is_list(Opts) -> + publish(Client, Topic, #{}, Payload, Opts). + +%% MQTT Version 5.0 +-spec(publish(client(), topic(), properties(), payload(), [pubopt()]) + -> ok | {ok, packet_id()} | {error, term()}). +publish(Client, Topic, Properties, Payload, Opts) + when is_binary(Topic), is_map(Properties), is_list(Opts) -> ok = emqx_mqtt_properties:validate(Properties), - publish(Client, #mqtt_message{qos = pubopt(qos, Options), - retain = pubopt(retain, Options), - topic = iolist_to_binary(Topic), + Retain = proplists:get_bool(retain, Opts), + QoS = ?QOS_I(proplists:get_value(qos, Opts, ?QOS_0)), + publish(Client, #mqtt_message{topic = Topic, + qos = QoS, + retain = Retain, properties = Properties, payload = iolist_to_binary(Payload)}). -%% @doc Publish MQTT Message. -spec(publish(client(), mqtt_message()) - -> ok | {ok, msgid()} | {error, term()}). + -> ok | {ok, packet_id()} | {error, term()}). publish(Client, Msg) when is_record(Msg, mqtt_message) -> gen_statem:call(Client, {publish, Msg}). -pubopt(qos, Opts) -> - proplists:get_value(qos, Opts, ?QOS0); -pubopt(retain, Opts) -> - lists:member(retain, Opts) orelse proplists:get_bool(retain, Opts). - --spec(subscribe(client(), binary() - | {binary(), mqtt_qos_name() | mqtt_qos()}) - -> {ok, mqtt_qos()} | {error, term()}). -subscribe(Client, Topic) when is_binary(Topic) -> - subscribe(Client, Topic, ?QOS_0); -subscribe(Client, {Topic, QoS}) when ?IS_QOS(QoS); is_atom(QoS) -> - subscribe(Client, Topic, ?QOS_I(QoS)); -subscribe(Client, Topics) when is_list(Topics) -> - case io_lib:printable_unicode_list(Topics) of - true -> subscribe(Client, [{Topics, ?QOS_0}]); - false -> Topics1 = [{iolist_to_binary(Topic), [{qos, ?QOS_I(QoS)}]} - || {Topic, QoS} <- Topics], - gen_statem:call(Client, {subscribe, Topics1}) - end. - --spec(subscribe(client(), string() | binary(), - mqtt_qos_name() | mqtt_qos() | [subopt()]) - -> {ok, mqtt_qos()} | {error, term()}). -subscribe(Client, Topic, QoS) when is_atom(QoS) -> - subscribe(Client, Topic, ?QOS_I(QoS)); -subscribe(Client, Topic, QoS) when ?IS_QOS(QoS) -> - subscribe(Client, Topic, [{qos, QoS}]); -subscribe(Client, Topic, Options) -> - gen_statem:call(Client, {subscribe, iolist_to_binary(Topic), Options}). - --spec(unsubscribe(client(), iolist()) -> ok | {error, term()}). +-spec(unsubscribe(client(), topic() | [topic()]) -> subscribe_ret()). unsubscribe(Client, Topic) when is_binary(Topic) -> unsubscribe(Client, [Topic]); unsubscribe(Client, Topics) when is_list(Topics) -> - case io_lib:printable_unicode_list(Topics) of - true -> unsubscribe(Client, [Topics]); - false -> - Topics1 = [iolist_to_binary(Topic) || Topic <- Topics], - gen_statem:call(Client, {unsubscribe, Topics1}) - end. + unsubscribe(Client, #{}, Topics). + +%% MQTT Version 5.0 +-spec(unsubscribe(client(), properties(), topic() | [topic()]) -> subscribe_ret()). +unsubscribe(Client, Properties, Topic) when is_map(Properties), is_binary(Topic) -> + unsubscribe(Client, Properties, [Topic]); +unsubscribe(Client, Properties, Topics) when is_map(Properties), is_list(Topics) -> + gen_statem:call(Client, {unsubscribe, Properties, Topics}). -spec(ping(client()) -> pong). ping(Client) -> gen_statem:call(Client, ping). -spec(disconnect(client()) -> ok). -disconnect(C) -> - disconnect(C, []). +disconnect(Client) -> + disconnect(Client, ?RC_SUCCESS). -disconnect(Client, Props) -> - gen_statem:call(Client, {disconnect, Props}). +-spec(disconnect(client(), reason_code()) -> ok). +disconnect(Client, ReasonCode) -> + disconnect(Client, ReasonCode, #{}). + +-spec(disconnect(client(), reason_code(), properties()) -> ok). +disconnect(Client, ReasonCode, Properties) -> + gen_statem:call(Client, {disconnect, ReasonCode, Properties}). %%-------------------------------------------------------------------- -%% APIs for broker test cases. +%% For test cases. %%-------------------------------------------------------------------- puback(Client, PacketId) when is_integer(PacketId) -> - gen_statem:cast(Client, {puback, PacketId}). + puback(Client, PacketId, ?RC_SUCCESS). +puback(Client, PacketId, ReasonCode) when is_integer(PacketId), + is_integer(ReasonCode) -> + puback(Client, PacketId, ReasonCode, #{}). +puback(Client, PacketId, ReasonCode, Properties) when is_integer(PacketId), + is_integer(ReasonCode), + is_map(Properties) -> + gen_statem:cast(Client, {puback, PacketId, ReasonCode, Properties}). pubrec(Client, PacketId) when is_integer(PacketId) -> - gen_statem:cast(Client, {pubrec, PacketId}). + pubrec(Client, PacketId, ?RC_SUCCESS). +pubrec(Client, PacketId, ReasonCode) when is_integer(PacketId), + is_integer(ReasonCode) -> + pubrec(Client, PacketId, ReasonCode, #{}). +pubrec(Client, PacketId, ReasonCode, Properties) when is_integer(PacketId), + is_integer(ReasonCode), + is_map(Properties) -> + gen_statem:cast(Client, {pubrec, PacketId, ReasonCode, Properties}). pubrel(Client, PacketId) when is_integer(PacketId) -> - gen_statem:cast(Client, {pubrel, PacketId}). + pubrel(Client, PacketId, ?RC_SUCCESS). +pubrel(Client, PacketId, ReasonCode) when is_integer(PacketId), + is_integer(ReasonCode) -> + pubrel(Client, PacketId, ReasonCode, #{}). +pubrel(Client, PacketId, ReasonCode, Properties) when is_integer(PacketId), + is_integer(ReasonCode), + is_map(Properties) -> + gen_statem:cast(Client, {pubrel, PacketId, ReasonCode, Properties}). pubcomp(Client, PacketId) when is_integer(PacketId) -> - gen_statem:cast(Client, {pubcomp, PacketId}). + pubcomp(Client, PacketId, ?RC_SUCCESS). +pubcomp(Client, PacketId, ReasonCode) when is_integer(PacketId), + is_integer(ReasonCode) -> + pubcomp(Client, PacketId, ReasonCode, #{}). +pubcomp(Client, PacketId, ReasonCode, Properties) when is_integer(PacketId), + is_integer(ReasonCode), + is_map(Properties) -> + gen_statem:cast(Client, {pubcomp, PacketId, ReasonCode, Properties}). -subscriptions(C) -> gen_statem:call(C, subscriptions). +subscriptions(Client) -> + gen_statem:call(Client, subscriptions). + +info(Client) -> + gen_statem:call(Client, info). %%-------------------------------------------------------------------- %% gen_statem callbacks @@ -255,7 +360,7 @@ init([Options]) -> process_flag(trap_exit, true), ClientId = case {proplists:get_value(proto_ver, Options, v4), proplists:get_value(client_id, Options)} of - {v5, undefined} -> undefined; + {v5, undefined} -> <<>>; {_ver, undefined} -> random_client_id(); {_ver, Id} -> iolist_to_binary(Id) end, @@ -263,28 +368,27 @@ init([Options]) -> port = 1883, hosts = [], sock_opts = [], + bridge_mode = false, client_id = ClientId, clean_start = true, proto_ver = ?MQTT_PROTO_V4, proto_name = <<"MQTT">>, keepalive = ?DEFAULT_KEEPALIVE, + force_ping = false, will_flag = false, will_msg = #mqtt_message{}, - ack_timeout = ?DEFAULT_ACK_TIMEOUT, - connect_timeout = ?DEFAULT_CONNECT_TIMEOUT, - force_ping = false, pending_calls = [], - subscribers = [], subscriptions = #{}, max_inflight = infinity, inflight = emqx_inflight:new(0), awaiting_rel = #{}, + properties = #{}, auto_ack = true, + ack_timeout = ?DEFAULT_ACK_TIMEOUT, retry_interval = 0, - last_packet_id = 1, - debug_mode = false}), - %% Connect and Send ConnAck - {ok, initialized, State}. + connect_timeout = ?DEFAULT_CONNECT_TIMEOUT, + last_packet_id = 1}), + {ok, initialized, init_parse_state(State)}. random_client_id() -> rand:seed(exsplus, erlang:timestamp()), @@ -344,12 +448,14 @@ init([{proto_ver, v5} | Opts], State) -> init([{will_topic, Topic} | Opts], State = #state{will_msg = WillMsg}) -> WillMsg1 = init_will_msg({topic, Topic}, WillMsg), init(Opts, State#state{will_flag = true, will_msg = WillMsg1}); +init([{will_props, Properties} | Opts], State = #state{will_msg = WillMsg}) -> + init(Opts, State#state{will_msg = init_will_msg({props, Properties}, WillMsg)}); init([{will_payload, Payload} | Opts], State = #state{will_msg = WillMsg}) -> - init(Opts, State#state{will_msg = init_will_msg({payload, Payload}, WillMsg)}); + init(Opts, State#state{will_msg = init_will_msg({payload, Payload}, WillMsg)}); init([{will_retain, Retain} | Opts], State = #state{will_msg = WillMsg}) -> - init(Opts, State#state{will_msg = init_will_msg({retain, Retain}, WillMsg)}); + init(Opts, State#state{will_msg = init_will_msg({retain, Retain}, WillMsg)}); init([{will_qos, QoS} | Opts], State = #state{will_msg = WillMsg}) -> - init(Opts, State#state{will_msg = init_will_msg({qos, QoS}, WillMsg)}); + init(Opts, State#state{will_msg = init_will_msg({qos, QoS}, WillMsg)}); init([{connect_timeout, Timeout}| Opts], State) -> init(Opts, State#state{connect_timeout = timer:seconds(Timeout)}); init([{ack_timeout, Timeout}| Opts], State) -> @@ -358,25 +464,29 @@ init([force_ping | Opts], State) -> init(Opts, State#state{force_ping = true}); init([{force_ping, ForcePing} | Opts], State) when is_boolean(ForcePing) -> init(Opts, State#state{force_ping = ForcePing}); +init([{properties, Properties} | Opts], State = #state{properties = InitProps}) -> + init(Opts, State#state{properties = maps:merge(InitProps, Properties)}); init([{max_inflight, infinity} | Opts], State) -> init(Opts, State#state{max_inflight = infinity, - inflight = emqx_inflight:new(0)}); + inflight = emqx_inflight:new(0)}); init([{max_inflight, I} | Opts], State) when is_integer(I) -> init(Opts, State#state{max_inflight = I, - inflight = emqx_inflight:new(I)}); + inflight = emqx_inflight:new(I)}); init([auto_ack | Opts], State) -> init(Opts, State#state{auto_ack = true}); init([{auto_ack, AutoAck} | Opts], State) when is_boolean(AutoAck) -> init(Opts, State#state{auto_ack = AutoAck}); init([{retry_interval, I} | Opts], State) -> init(Opts, State#state{retry_interval = timer:seconds(I)}); -init([{debug_mode, Mode} | Opts], State) when is_boolean(Mode) -> - init(Opts, State#state{debug_mode = Mode}); +init([{bridge_mode, Mode} | Opts], State) when is_boolean(Mode) -> + init(Opts, State#state{bridge_mode = Mode}); init([_Opt | Opts], State) -> init(Opts, State). init_will_msg({topic, Topic}, WillMsg) -> WillMsg#mqtt_message{topic = iolist_to_binary(Topic)}; +init_will_msg({props, Properties}, WillMsg) -> + WillMsg#mqtt_message{properties = Properties}; init_will_msg({payload, Payload}, WillMsg) -> WillMsg#mqtt_message{payload = iolist_to_binary(Payload)}; init_will_msg({retain, Retain}, WillMsg) when is_boolean(Retain) -> @@ -384,104 +494,123 @@ init_will_msg({retain, Retain}, WillMsg) when is_boolean(Retain) -> init_will_msg({qos, QoS}, WillMsg) -> WillMsg#mqtt_message{qos = ?QOS_I(QoS)}. +init_parse_state(State = #state{proto_ver = Ver, properties = Properties}) -> + Size = maps:get('Maximum-Packet-Size', Properties, ?MAX_PACKET_SIZE), + State#state{parse_state = emqx_parser:initial_state([{max_len, Size}, + {version, Ver}])}. + callback_mode() -> state_functions. -initialized({call, From}, connect, State = #state{connect_timeout = Timeout}) -> - case sock_connect(State) of - {ok, State1} -> - case mqtt_connect(State1) of - {ok, State2} -> +initialized({call, From}, connect, State = #state{sock_opts = SockOpts, + connect_timeout = Timeout}) -> + case sock_connect(hosts(State), SockOpts, Timeout) of + {ok, Sock} -> + case mqtt_connect(run_sock(State#state{socket = Sock})) of + {ok, NewState} -> {next_state, waiting_for_connack, - add_call(new_call(connect, From), State2), [Timeout]}; - Err = {error, Reason} -> - {stop_and_reply, Reason, [{reply, From, Err}]} + add_call(new_call(connect, From), NewState), [Timeout]}; + Error = {error, Reason} -> + {stop_and_reply, Reason, [{reply, From, Error}]} end; - Err = {error, Reason} -> - {stop_and_reply, Reason, [{reply, From, Err}]} + Error = {error, Reason} -> + {stop_and_reply, Reason, [{reply, From, Error}]} end; -initialized(EventType, EventContent, StateData) -> - handle_event(EventType, EventContent, StateData). +initialized(EventType, EventContent, State) -> + handle_event(EventType, EventContent, initialized, State). -sock_connect(State) -> - sock_connect(get_hosts(State), {error, no_hosts}, State). - -get_hosts(#state{hosts = [], host = Host, port = Port}) -> - [{Host, Port}]; -get_hosts(#state{hosts = Hosts}) -> Hosts. - -sock_connect([], Err, _State) -> - Err; -sock_connect([{Host, Port} | Hosts], _Err, State = #state{sock_opts = SockOpts}) -> - case emqx_client_sock:connect(self(), Host, Port, SockOpts) of - {ok, Socket, Receiver} -> - {ok, State#state{socket = Socket, receiver = Receiver}}; - Err = {error, _Reason} -> - sock_connect(Hosts, Err, State) - end. - -mqtt_connect(State = #state{client_id = ClientId, - clean_start = CleanStart, - username = Username, - password = Password, - proto_ver = ProtoVer, - proto_name = ProtoName, - keepalive = KeepAlive, - will_flag = WillFlag, - will_msg = WillMsg}) -> - #mqtt_message{qos = WillQos, - retain = WillRetain, - topic = WillTopic, - payload = WillPayload} = WillMsg, +mqtt_connect(State = #state{client_id = ClientId, + clean_start = CleanStart, + bridge_mode = IsBridge, + username = Username, + password = Password, + proto_ver = ProtoVer, + proto_name = ProtoName, + keepalive = KeepAlive, + will_flag = WillFlag, + will_msg = WillMsg, + properties = Properties}) -> + ?WILL_MSG(WillQos, WillRetain, WillTopic, WillProps, WillPayload) = WillMsg, + ConnProps = emqx_mqtt_properties:filter(?CONNECT, maps:to_list(Properties)), send(?CONNECT_PACKET( - #mqtt_packet_connect{client_id = ClientId, - clean_start = CleanStart, - proto_ver = ProtoVer, - proto_name = ProtoName, - will_flag = WillFlag, - will_retain = WillRetain, - will_qos = WillQos, - keep_alive = KeepAlive, - will_topic = WillTopic, - will_msg = WillPayload, - username = Username, - password = Password}), State). + #mqtt_packet_connect{proto_ver = ProtoVer, + proto_name = ProtoName, + is_bridge = IsBridge, + clean_start = CleanStart, + will_flag = WillFlag, + will_qos = WillQos, + will_retain = WillRetain, + keepalive = KeepAlive, + properties = ConnProps, + client_id = ClientId, + will_props = WillProps, + will_topic = WillTopic, + will_payload = WillPayload, + username = Username, + password = Password}), State). -waiting_for_connack(cast, ?CONNACK_PACKET(?CONNACK_ACCEPT, - _SessPresent, - _Properties), State) -> +waiting_for_connack(cast, ?CONNACK_PACKET(?RC_SUCCESS, + SessPresent, + Properties), + State = #state{properties = AllProps}) -> case take_call(connect, State) of {value, #call{from = From}, State1} -> - {next_state, connected, - ensure_keepalive_timer(ensure_ack_timer(State1)), - [{reply, From, {ok, self()}}]}; + AllProps1 = case Properties of + undefined -> AllProps; + _ -> maps:merge(AllProps, Properties) + end, + Reply = {ok, self(), Properties}, + State2 = State1#state{properties = AllProps1, + session_present = SessPresent}, + {next_state, connected, ensure_keepalive_timer(State2), + [{reply, From, Reply}]}; false -> - io:format("Cannot find call: ~p~n", [State#state.pending_calls]), - {stop, {error, unexpected_connack}} + {stop, bad_connack} end; waiting_for_connack(cast, ?CONNACK_PACKET(ReasonCode, _SessPresent, - _Properties), State) -> - reply_connack_error(emqx_packet:connack_error(ReasonCode), State); + Properties), State) -> + Reason = emqx_reason_codes:name(ReasonCode), + case take_call(connect, State) of + {value, #call{from = From}, _State} -> + Reply = {error, {Reason, Properties}}, + {stop_and_reply, Reason, [{reply, From, Reply}]}; + false -> {stop, connack_error} + end; waiting_for_connack(timeout, _Timeout, State) -> - reply_connack_error(connack_timeout, State); - -waiting_for_connack(EventType, EventContent, StateData) -> - handle_event(EventType, EventContent, StateData). - -reply_connack_error(Reason, State) -> - Error = {error, Reason}, case take_call(connect, State) of - {value, #call{from = From}, State1} -> - {stop_and_reply, Error, [{reply, From, Error}], State1}; - false -> {stop, Error} - end. + {value, #call{from = From}, _State} -> + Reply = {error, connack_timeout}, + {stop_and_reply, connack_timeout, [{reply, From, Reply}]}; + false -> {stop, connack_timeout} + end; + +waiting_for_connack(EventType, EventContent, State) -> + handle_event(EventType, EventContent, waiting_for_connack, State). connected({call, From}, subscriptions, State = #state{subscriptions = Subscriptions}) -> {keep_state, State, [{reply, From, maps:to_list(Subscriptions)}]}; +connected({call, From}, info, State) -> + Info = lists:zip(record_info(fields, state), tl(tuple_to_list(State))), + {keep_state, State, [{reply, From, Info}]}; + +connected({call, From}, SubReq = {subscribe, Properties, Topics}, + State = #state{last_packet_id = PacketId, subscriptions = Subscriptions}) -> + case send(?SUBSCRIBE_PACKET(PacketId, Properties, Topics), State) of + {ok, NewState} -> + Call = new_call({subscribe, PacketId}, From, SubReq), + Subscriptions1 = + lists:foldl(fun({Topic, Opts}, Acc) -> + maps:put(Topic, Opts, Acc) + end, Subscriptions, Topics), + {keep_state, ensure_ack_timer(add_call(Call,NewState#state{subscriptions = Subscriptions1}))}; + Error = {error, Reason} -> + {stop_and_reply, Reason, [{reply, From, Error}]} + end; + connected({call, From}, {publish, Msg = #mqtt_message{qos = ?QOS_0}}, State) -> case send(Msg, State) of {ok, NewState} -> @@ -508,36 +637,9 @@ connected({call, From}, {publish, Msg = #mqtt_message{qos = Qos}}, end end; -connected({call, From}, SubReq = {subscribe, Topic, SubOpts}, - State= #state{last_packet_id = PacketId, subscriptions = Subscriptions}) -> - %%TODO: handle qos... - QoS = proplists:get_value(qos, SubOpts, ?QOS_0), - case send(?SUBSCRIBE_PACKET(PacketId, [{Topic, QoS}]), State) of - {ok, NewState} -> - Call = new_call({subscribe, PacketId}, From, SubReq), - Subscriptions1 = maps:put(Topic, SubOpts, Subscriptions), - {keep_state, ensure_ack_timer(add_call(Call, NewState#state{subscriptions = Subscriptions1}))}; - Error = {error, Reason} -> - {stop_and_reply, Reason, [{reply, From, Error}]} - end; - -connected({call, From}, SubReq = {subscribe, Topics}, - State= #state{last_packet_id = PacketId, subscriptions = Subscriptions}) -> - case send(?SUBSCRIBE_PACKET(PacketId, Topics), State) of - {ok, NewState} -> - Call = new_call({subscribe, PacketId}, From, SubReq), - Subscriptions1 = - lists:fold(fun({Topic, SubOpts}, Acc) -> - maps:put(Topic, SubOpts, Acc) - end, Subscriptions, Topics), - {keep_state, ensure_ack_timer(add_call(Call, NewState#state{subscriptions = Subscriptions1}))}; - Error = {error, Reason} -> - {stop_and_reply, Reason, [{reply, From, Error}]} - end; - -connected({call, From}, UnsubReq = {unsubscribe, Topics}, +connected({call, From}, UnsubReq = {unsubscribe, Properties, Topics}, State = #state{last_packet_id = PacketId}) -> - case send(?UNSUBSCRIBE_PACKET(PacketId, Topics), State) of + case send(?UNSUBSCRIBE_PACKET(PacketId, Properties, Topics), State) of {ok, NewState} -> Call = new_call({unsubscribe, PacketId}, From, UnsubReq), {keep_state, ensure_ack_timer(add_call(Call, NewState))}; @@ -554,25 +656,25 @@ connected({call, From}, ping, State) -> {stop_and_reply, Reason, [{reply, From, Error}]} end; -connected({call, From}, disconnect, State) -> - case send(?PACKET(?DISCONNECT), State) of +connected({call, From}, {disconnect, ReasonCode, Properties}, State) -> + case send(?DISCONNECT_PACKET(ReasonCode, Properties), State) of {ok, NewState} -> {stop_and_reply, normal, [{reply, From, ok}], NewState}; - Error = {error, _Reason} -> - {stop_and_reply, disconnected, [{reply, From, Error}]} + Error = {error, Reason} -> + {stop_and_reply, Reason, [{reply, From, Error}]} end; -connected(cast, {puback, PacketId}, State) -> - send_puback(?PUBACK_PACKET(?PUBACK, PacketId), State); +connected(cast, {puback, PacketId, ReasonCode, Properties}, State) -> + send_puback(?PUBACK_PACKET(PacketId, ReasonCode, Properties), State); -connected(cast, {pubrec, PacketId}, State) -> - send_puback(?PUBACK_PACKET(?PUBREC, PacketId), State); +connected(cast, {pubrec, PacketId, ReasonCode, Properties}, State) -> + send_puback(?PUBREC_PACKET(PacketId, ReasonCode, Properties), State); -connected(cast, {pubrel, PacketId}, State) -> - send_puback(?PUBREL_PACKET(PacketId), State); +connected(cast, {pubrel, PacketId, ReasonCode, Properties}, State) -> + send_puback(?PUBREL_PACKET(PacketId, ReasonCode, Properties), State); -connected(cast, {pubcomp, PacketId}, State) -> - send_puback(?PUBCOMP_PACKET(PacketId), State); +connected(cast, {pubcomp, PacketId, ReasonCode, Properties}, State) -> + send_puback(?PUBCOMP_PACKET(PacketId, ReasonCode, Properties), State); connected(cast, Packet = ?PUBLISH_PACKET(?QOS_0, _PacketId), State) -> {keep_state, deliver_msg(packet_to_msg(Packet), State)}; @@ -594,14 +696,16 @@ connected(cast, Packet = ?PUBLISH_PACKET(?QOS_2, PacketId), Stop -> Stop end; -connected(cast, ?PUBACK_PACKET(PacketId), +connected(cast, ?PUBACK_PACKET(PacketId, ReasonCode, Properties), State = #state{owner = Owner, inflight = Inflight}) -> case Inflight:lookup(PacketId) of {value, {publish, #mqtt_message{packet_id = PacketId}, _Ts}} -> - Owner ! {puback, PacketId}, + Owner ! {puback, #{packet_id => PacketId, + reason_code => ReasonCode, + properties => Properties}}, {keep_state, State#state{inflight = Inflight:delete(PacketId)}}; none -> - ?LOG(warning, "Unexpected PUBACK: ~p", [PacketId]), + emqx_logger:warning("Unexpected PUBACK: ~p", [PacketId]), {keep_state, State} end; @@ -612,16 +716,16 @@ connected(cast, ?PUBREC_PACKET(PacketId), State = #state{inflight = Inflight}) - Inflight1 = Inflight:update(PacketId, {pubrel, PacketId, os:timestamp()}), State#state{inflight = Inflight1}; {value, {pubrel, _Ref, _Ts}} -> - ?LOG(warning, "Duplicated PUBREC Packet: ~p", [PacketId]), + emqx_logger:warning("Duplicated PUBREC Packet: ~p", [PacketId]), State; none -> - ?LOG(warning, "Unexpected PUBREC Packet: ~p", [PacketId]), + emqx_logger:warning("Unexpected PUBREC Packet: ~p", [PacketId]), State end); %%TODO::... if auto_ack is false, should we take PacketId from the map? -connected(cast, ?PUBREL_PACKET(PacketId), State = #state{awaiting_rel = AwaitingRel, - auto_ack = AutoAck}) -> +connected(cast, ?PUBREL_PACKET(PacketId), + State = #state{awaiting_rel = AwaitingRel, auto_ack = AutoAck}) -> case maps:take(PacketId, AwaitingRel) of {Packet, AwaitingRel1} -> NewState = deliver_msg(packet_to_msg(Packet), @@ -631,54 +735,60 @@ connected(cast, ?PUBREL_PACKET(PacketId), State = #state{awaiting_rel = Awaiting false -> {keep_state, NewState} end; error -> - ?LOG(warning, "Unexpected PUBREL: ~p", [PacketId]), + emqx_logger:warning("Unexpected PUBREL: ~p", [PacketId]), {keep_state, State} end; -connected(cast, ?PUBCOMP_PACKET(PacketId), State = #state{owner = Owner, inflight = Inflight}) -> +connected(cast, ?PUBCOMP_PACKET(PacketId, ReasonCode, Properties), + State = #state{owner = Owner, inflight = Inflight}) -> case Inflight:lookup(PacketId) of {value, {pubrel, _PacketId, _Ts}} -> - Owner ! {pubcomp, PacketId}, + Owner ! {puback, #{packet_id => PacketId, + reason_code => ReasonCode, + properties => Properties}}, {keep_state, State#state{inflight = Inflight:delete(PacketId)}}; none -> - ?LOG(warning, "Unexpected PUBCOMP Packet: ~p", [PacketId]), + emqx_logger:warning("Unexpected PUBCOMP Packet: ~p", [PacketId]), {keep_state, State} end; -%%TODO: handle suback... -connected(cast, ?SUBACK_PACKET(PacketId, QosTable), - State = #state{subscriptions = Subscriptions}) -> - ?LOG(info, "SUBACK(~p) Received", [PacketId]), +connected(cast, ?SUBACK_PACKET(PacketId, Properties, ReasonCodes), + State = #state{subscriptions = _Subscriptions}) -> case take_call({subscribe, PacketId}, State) of - {value, #call{from = From}, State1} -> - {keep_state, State1, [{reply, From, ok}]}; + {value, #call{from = From}, NewState} -> + %%TODO: Merge reason codes to subscriptions? + Reply = {ok, Properties, ReasonCodes}, + {keep_state, NewState, [{reply, From, Reply}]}; false -> {keep_state, State} end; -%%TODO: handle unsuback... -connected(cast, ?UNSUBACK_PACKET(PacketId), +connected(cast, ?UNSUBACK_PACKET(PacketId, Properties, ReasonCodes), State = #state{subscriptions = Subscriptions}) -> - ?LOG(info, "UNSUBACK(~p) received", [PacketId]), case take_call({unsubscribe, PacketId}, State) of - {value, #call{from = From, req = {_, Topics}}, State1} -> - {keep_state, State1#state{subscriptions = - lists:foldl(fun(Topic, Subs) -> - maps:remove(Topic, Subs) - end, Subscriptions, Topics)}, - [{reply, From, ok}]}; + {value, #call{from = From, req = {_, Topics}}, NewState} -> + Subscriptions1 = + lists:foldl(fun(Topic, Acc) -> + maps:remove(Topic, Acc) + end, Subscriptions, Topics), + {keep_state, NewState#state{subscriptions = Subscriptions1}, + [{reply, From, {ok, Properties, ReasonCodes}}]}; false -> {keep_state, State} end; -%%TODO: handle PINGRESP... connected(cast, ?PACKET(?PINGRESP), State = #state{pending_calls = []}) -> {keep_state, State}; connected(cast, ?PACKET(?PINGRESP), State) -> case take_call(ping, State) of - {value, #call{from = From}, State1} -> - {keep_state, State1, [{reply, From, pong}]}; + {value, #call{from = From}, NewState} -> + {keep_state, NewState, [{reply, From, pong}]}; false -> {keep_state, State} end; +connected(cast, ?DISCONNECT_PACKET(ReasonCode, Properties), + State = #state{owner = Owner}) -> + Owner ! {disconnected, ReasonCode, Properties}, + {stop, disconnected, State}; + connected(info, {timeout, _TRef, keepalive}, State = #state{force_ping = true}) -> case send(?PACKET(?PINGREQ), State) of {ok, NewState} -> @@ -687,68 +797,77 @@ connected(info, {timeout, _TRef, keepalive}, State = #state{force_ping = true}) end; connected(info, {timeout, TRef, keepalive}, - State = #state{socket = Socket, keepalive_timer = TRef}) -> - case should_ping(Socket) of + State = #state{socket = Sock, keepalive_timer = TRef}) -> + case should_ping(Sock) of true -> case send(?PACKET(?PINGREQ), State) of {ok, NewState} -> - {keep_state, ensure_keepalive_timer(NewState)}; + {keep_state, ensure_keepalive_timer(NewState), [hibernate]}; Error -> {stop, Error} end; false -> - {keep_state, ensure_keepalive_timer(State)}; + {keep_state, ensure_keepalive_timer(State), [hibernate]}; {error, Reason} -> - {stop, {error, Reason}} + {stop, Reason} end; -connected(info, {timeout, TRef, ack}, State = #state{ack_timer = TRef, - ack_timeout = Timeout, +connected(info, {timeout, TRef, ack}, State = #state{ack_timer = TRef, + ack_timeout = Timeout, pending_calls = Calls}) -> NewState = State#state{ack_timer = undefined, pending_calls = timeout_calls(Timeout, Calls)}, {keep_state, ensure_ack_timer(NewState)}; connected(info, {timeout, TRef, retry}, State = #state{retry_timer = TRef, - inflight = Inflight}) -> + inflight = Inflight}) -> case Inflight:is_empty() of true -> {keep_state, State#state{retry_timer = undefined}}; false -> retry_send(State) end; -connected(EventType, EventContent, StateData) -> - handle_event(EventType, EventContent, StateData). +connected(EventType, EventContent, Data) -> + handle_event(EventType, EventContent, connected, Data). should_ping(Sock) -> case emqx_client_sock:getstat(Sock, [send_oct]) of {ok, [{send_oct, Val}]} -> OldVal = get(send_oct), put(send_oct, Val), OldVal == undefined orelse OldVal == Val; - Err = {error, _Reason} -> - Err + Error = {error, _Reason} -> + Error end. -handle_event(info, {'EXIT', Owner, Reason}, #state{owner = Owner}) -> - {stop, Reason}; +handle_event(info, {TcpOrSsL, _Sock, Data}, _StateName, State) + when TcpOrSsL =:= tcp; TcpOrSsL =:= ssl -> + emqx_logger:debug("RECV Data: ~p", [Data]), + receive_loop(Data, run_sock(State)); -handle_event(info, {'EXIT', Receiver, Reason}, #state{receiver = Receiver}) -> - {stop, Reason}; - -handle_event(info, {inet_reply, _Sock, ok}, State) -> - {keep_state, State}; - -handle_event(info, {inet_reply, _Sock, {error, Reason}}, State) -> +handle_event(info, {Error, _Sock, Reason}, _StateName, State) + when Error =:= tcp_error; Error =:= ssl_error -> {stop, Reason, State}; -handle_event(EventType, EventContent, State) -> - ?LOG(error, "Unexpected Event: (~p, ~p)", [EventType, EventContent]), - {keep_state, State}. +handle_event(info, {Closed, _Sock}, _StateName, State) + when Closed =:= tcp_closed; Closed =:= ssl_closed -> + {stop, Closed, State}; + +handle_event(info, {'EXIT', Owner, Reason}, _, #state{owner = Owner}) -> + {stop, Reason}; + +handle_event(info, {inet_reply, _Sock, ok}, _, State) -> + {keep_state, State}; + +handle_event(info, {inet_reply, _Sock, {error, Reason}}, _, State) -> + {stop, Reason, State}; + +handle_event(EventType, EventContent, StateName, StateData) -> + emqx_logger:error("State: ~s, Unexpected Event: (~p, ~p)", + [StateName, EventType, EventContent]), + {keep_state, StateData}. %% Mandatory callback functions terminate(_Reason, _State, #state{socket = undefined}) -> ok; -terminate(_Reason, _State, #state{socket = Socket, - receiver = Receiver}) -> - emqx_client_sock:stop(Receiver), +terminate(_Reason, _State, #state{socket = Socket}) -> emqx_client_sock:close(Socket). code_change(_Vsn, State, Data, _Extra) -> @@ -758,24 +877,27 @@ code_change(_Vsn, State, Data, _Extra) -> %% Internal functions %%-------------------------------------------------------------------- +ensure_keepalive_timer(State = ?PROPERTY('Server-Keep-Alive', Secs)) -> + ensure_keepalive_timer(timer:seconds(Secs), State); ensure_keepalive_timer(State = #state{keepalive = 0}) -> State; -ensure_keepalive_timer(State = #state{keepalive = Keepalive}) -> - TRef = erlang:start_timer(Keepalive, self(), keepalive), - State#state{keepalive_timer = TRef}. +ensure_keepalive_timer(State = #state{keepalive = I}) -> + ensure_keepalive_timer(I, State). +ensure_keepalive_timer(I, State) when is_integer(I) -> + State#state{keepalive_timer = erlang:start_timer(I, self(), keepalive)}. new_call(Id, From) -> new_call(Id, From, undefined). new_call(Id, From, Req) -> #call{id = Id, from = From, req = Req, ts = os:timestamp()}. -add_call(Call, State = #state{pending_calls = Calls}) -> - State#state{pending_calls = [Call | Calls]}. +add_call(Call, Data = #state{pending_calls = Calls}) -> + Data#state{pending_calls = [Call | Calls]}. -take_call(Id, State = #state{pending_calls = Calls}) -> +take_call(Id, Data = #state{pending_calls = Calls}) -> case lists:keytake(Id, #call.id, Calls) of {value, Call, Left} -> - {value, Call, State#state{pending_calls = Left}}; + {value, Call, Data#state{pending_calls = Left}}; false -> false end. @@ -790,15 +912,16 @@ timeout_calls(Now, Timeout, Calls) -> end end, [], Calls). -ensure_ack_timer(State = #state{ack_timer = undefined, - ack_timeout = Timeout, +ensure_ack_timer(State = #state{ack_timer = undefined, + ack_timeout = Timeout, pending_calls = Calls}) when length(Calls) > 0 -> State#state{ack_timer = erlang:start_timer(Timeout, self(), ack)}; ensure_ack_timer(State) -> State. ensure_retry_timer(State = #state{retry_interval = Interval}) -> ensure_retry_timer(Interval, State). -ensure_retry_timer(Interval, State = #state{retry_timer = undefined}) when Interval > 0 -> +ensure_retry_timer(Interval, State = #state{retry_timer = undefined}) + when Interval > 0 -> State#state{retry_timer = erlang:start_timer(Interval, self(), retry)}; ensure_retry_timer(_Interval, State) -> State. @@ -806,7 +929,7 @@ ensure_retry_timer(_Interval, State) -> retry_send(State = #state{inflight = Inflight}) -> SortFun = fun({_, _, Ts1}, {_, _, Ts2}) -> Ts1 < Ts2 end, Msgs = lists:sort(SortFun, Inflight:values()), - retry_send(Msgs, os:timestamp(), State). + retry_send(Msgs, os:timestamp(), State ). retry_send([], _Now, State) -> {keep_state, ensure_retry_timer(State)}; @@ -839,36 +962,61 @@ retry_send(pubrel, PacketId, Now, State = #state{inflight = Inflight}) -> Error end. -deliver_msg(#mqtt_message{packet_id = PacketId, - qos = QoS, - retain = Retain, +deliver_msg(#mqtt_message{qos = QoS, dup = Dup, + retain = Retain, topic = Topic, - properties = Props, + packet_id = PacketId, + properties = Properties, payload = Payload}, State = #state{owner = Owner}) -> - Metadata = #{mid => PacketId, qos => QoS, dup => Dup, - retain => Retain, properties => Props}, - Owner ! {publish, Topic, Metadata, Payload}, State. + Owner ! {publish, #{qos => QoS, dup => Dup, retain => Retain, + packet_id => PacketId, topic => Topic, + properties => Properties, payload => Payload}}, + State. -packet_to_msg(?PUBLISH_PACKET(QoS, Topic, PacketId, Payload)) -> - #mqtt_message{qos = QoS, packet_id = PacketId, - topic = Topic, payload = Payload}. +packet_to_msg(?PUBLISH_PACKET(Header, Topic, PacketId, Properties, Payload)) -> + #mqtt_packet_header{qos = QoS, retain = R, dup = Dup} = Header, + #mqtt_message{qos = QoS, retain = R, dup = Dup, + packet_id = PacketId, topic = Topic, + properties = Properties, payload = Payload}. -msg_to_packet(#mqtt_message{packet_id = PacketId, - qos = Qos, - retain = Retain, - dup = Dup, - topic = Topic, - payload = Payload}) -> +msg_to_packet(#mqtt_message{qos = Qos, + dup = Dup, + retain = Retain, + topic = Topic, + packet_id = PacketId, + properties = Properties, + payload = Payload}) -> #mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH, qos = Qos, retain = Retain, dup = Dup}, variable = #mqtt_packet_publish{topic_name = Topic, - packet_id = PacketId}, + packet_id = PacketId, + properties = Properties}, payload = Payload}. + +%%-------------------------------------------------------------------- +%% Socket Connect/Send + +sock_connect(Hosts, SockOpts, Timeout) -> + sock_connect(Hosts, SockOpts, Timeout, {error, no_hosts}). + +sock_connect([], _SockOpts, _Timeout, LastErr) -> + LastErr; +sock_connect([{Host, Port} | Hosts], SockOpts, Timeout, _LastErr) -> + case emqx_client_sock:connect(Host, Port, SockOpts, Timeout) of + {ok, Socket} -> {ok, Socket}; + Err = {error, _Reason} -> + sock_connect(Hosts, SockOpts, Timeout, Err) + end. + +hosts(#state{hosts = [], host = Host, port = Port}) -> + [{Host, Port}]; +hosts(#state{hosts = Hosts}) -> Hosts. + send_puback(Packet, State) -> case send(Packet, State) of {ok, NewState} -> {keep_state, NewState}; @@ -878,17 +1026,43 @@ send_puback(Packet, State) -> send(Msg, State) when is_record(Msg, mqtt_message) -> send(msg_to_packet(Msg), State); -send(Packet, StateData = #state{socket = Socket}) +send(Packet, State = #state{socket = Sock, proto_ver = Ver}) when is_record(Packet, mqtt_packet) -> - Data = emqx_serializer:serialize(Packet), - case emqx_client_sock:send(Socket, Data) of - ok -> {ok, next_msg_id(StateData)}; - {error, Reason} -> {error, Reason} + Data = emqx_serializer:serialize(Packet, [{version, Ver}]), + emqx_logger:debug("SEND Data: ~p", [Data]), + case emqx_client_sock:send(Sock, Data) of + ok -> {ok, next_packet_id(State)}; + Error -> Error end. -next_msg_id(State = #state{last_packet_id = 16#ffff}) -> +run_sock(State = #state{socket = Sock}) -> + emqx_client_sock:setopts(Sock, [{active, once}]), State. + +%%-------------------------------------------------------------------- +%% Receive Loop + +receive_loop(<<>>, State) -> + {keep_state, State}; + +receive_loop(Bytes, State = #state{parse_state = ParseState}) -> + case catch emqx_parser:parse(Bytes, ParseState) of + {ok, Packet, Rest} -> + ok = gen_statem:cast(self(), Packet), + receive_loop(Rest, init_parse_state(State)); + {more, NewParseState} -> + {keep_state, State#state{parse_state = NewParseState}}; + {error, Reason} -> + {stop, Reason}; + {'EXIT', Error} -> + {stop, Error} + end. + +%%-------------------------------------------------------------------- +%% Next packet id + +next_packet_id(State = #state{last_packet_id = 16#ffff}) -> State#state{last_packet_id = 1}; -next_msg_id(State = #state{last_packet_id = Id}) -> +next_packet_id(State = #state{last_packet_id = Id}) -> State#state{last_packet_id = Id + 1}. diff --git a/src/emqx_client_sock.erl b/src/emqx_client_sock.erl index febacd1d3..a7bc5aa15 100644 --- a/src/emqx_client_sock.erl +++ b/src/emqx_client_sock.erl @@ -16,15 +16,10 @@ -module(emqx_client_sock). --include("emqx_client.hrl"). - --export([connect/4, connect/5, send/2, close/1, stop/1]). +-export([connect/4, send/2, close/1]). -export([sockname/1, setopts/2, getstat/2]). -%% Internal export --export([receiver/2, receiver_loop/3]). - -record(ssl_socket, {tcp, ssl}). -type(socket() :: inet:socket() | #ssl_socket{}). @@ -32,37 +27,23 @@ -type(sockname() :: {inet:ip_address(), inet:port_number()}). -type(option() :: gen_tcp:connect_option() - | {ssl_options, [ssl:ssl_option()]}). + | {ssl_opts, [ssl:ssl_option()]}). -export_type([socket/0, option/0]). -%%-------------------------------------------------------------------- -%% Socket API -%%-------------------------------------------------------------------- +-define(DEFAULT_TCP_OPTIONS, [binary, {packet, raw}, {active, false}, + {nodelay, true}, {reuseaddr, true}]). --spec(connect(pid(), inet:ip_address() | inet:hostname(), - inet:port_number(), [option()]) +-spec(connect(inet:ip_address() | inet:hostname(), + inet:port_number(), [option()], timeout()) -> {ok, socket()} | {error, term()}). -connect(ClientPid, Host, Port, SockOpts) -> - connect(ClientPid, Host, Port, SockOpts, ?DEFAULT_CONNECT_TIMEOUT). - -connect(ClientPid, Host, Port, SockOpts, Timeout) -> - case do_connect(Host, Port, SockOpts, Timeout) of - {ok, Sock} -> - Receiver = spawn_link(?MODULE, receiver, [ClientPid, Sock]), - ok = controlling_process(Sock, Receiver), - {ok, Sock, Receiver}; - Error -> - Error - end. - -do_connect(Host, Port, SockOpts, Timeout) -> +connect(Host, Port, SockOpts, Timeout) -> TcpOpts = emqx_misc:merge_opts(?DEFAULT_TCP_OPTIONS, - lists:keydelete(ssl_options, 1, SockOpts)), + lists:keydelete(ssl_opts, 1, SockOpts)), case gen_tcp:connect(Host, Port, TcpOpts, Timeout) of {ok, Sock} -> - case lists:keyfind(ssl_options, 1, SockOpts) of - {ssl_options, SslOpts} -> + case lists:keyfind(ssl_opts, 1, SockOpts) of + {ssl_opts, SslOpts} -> ssl_upgrade(Sock, SslOpts, Timeout); false -> {ok, Sock} end; @@ -73,23 +54,17 @@ do_connect(Host, Port, SockOpts, Timeout) -> ssl_upgrade(Sock, SslOpts, Timeout) -> case ssl:connect(Sock, SslOpts, Timeout) of {ok, SslSock} -> + ok = ssl:controlling_process(SslSock, self()), {ok, #ssl_socket{tcp = Sock, ssl = SslSock}}; {error, Reason} -> {error, Reason} end. --spec(controlling_process(socket(), pid()) -> ok). -controlling_process(Sock, Pid) when is_port(Sock) -> - gen_tcp:controlling_process(Sock, Pid); -controlling_process(#ssl_socket{ssl = SslSock}, Pid) -> - ssl:controlling_process(SslSock, Pid). - -spec(send(socket(), iodata()) -> ok | {error, einval | closed}). send(Sock, Data) when is_port(Sock) -> try erlang:port_command(Sock, Data) of true -> ok catch - error:badarg -> - {error, einval} + error:badarg -> {error, einval} end; send(#ssl_socket{ssl = SslSock}, Data) -> ssl:send(SslSock, Data). @@ -100,10 +75,6 @@ close(Sock) when is_port(Sock) -> close(#ssl_socket{ssl = SslSock}) -> ssl:close(SslSock). --spec(stop(Receiver :: pid()) -> stop). -stop(Receiver) -> - Receiver ! stop. - -spec(setopts(socket(), [gen_tcp:option() | ssl:socketoption()]) -> ok). setopts(Sock, Opts) when is_port(Sock) -> inet:setopts(Sock, Opts); @@ -123,50 +94,3 @@ sockname(Sock) when is_port(Sock) -> sockname(#ssl_socket{ssl = SslSock}) -> ssl:sockname(SslSock). -%%-------------------------------------------------------------------- -%% Receiver -%%-------------------------------------------------------------------- - -receiver(ClientPid, Sock) -> - receiver_activate(ClientPid, Sock, emqx_parser:initial_state()). - -receiver_activate(ClientPid, Sock, ParseState) -> - setopts(Sock, [{active, once}]), - erlang:hibernate(?MODULE, receiver_loop, [ClientPid, Sock, ParseState]). - -receiver_loop(ClientPid, Sock, ParseState) -> - receive - {TcpOrSsL, _Sock, Data} when TcpOrSsL =:= tcp; - TcpOrSsL =:= ssl -> - case parse_received_bytes(ClientPid, Data, ParseState) of - {ok, NewParseState} -> - receiver_activate(ClientPid, Sock, NewParseState); - {error, Error} -> - exit({frame_error, Error}) - end; - {Error, _Sock, Reason} when Error =:= tcp_error; - Error =:= ssl_error -> - exit({Error, Reason}); - {Closed, _Sock} when Closed =:= tcp_closed; - Closed =:= ssl_closed -> - exit(Closed); - stop -> - close(Sock) - end. - -parse_received_bytes(_ClientPid, <<>>, ParseState) -> - {ok, ParseState}; - -parse_received_bytes(ClientPid, Data, ParseState) -> - io:format("RECV Data: ~p~n", [Data]), - case emqx_parser:parse(Data, ParseState) of - {more, ParseState1} -> - {ok, ParseState1}; - {ok, Packet, Rest} -> - io:format("RECV Packet: ~p~n", [Packet]), - gen_statem:cast(ClientPid, Packet), - parse_received_bytes(ClientPid, Rest, emqx_parser:initial_state()); - {error, Error} -> - {error, Error} - end. - diff --git a/src/emqx_connection.erl b/src/emqx_connection.erl index c034e4701..930424d38 100644 --- a/src/emqx_connection.erl +++ b/src/emqx_connection.erl @@ -1,18 +1,18 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%% -%% 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. -%%-------------------------------------------------------------------- +%%%=================================================================== +%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%%% +%%% Licensed under the Apache License, Version 2.0 (the "License"); +%%% you may not use this file except in compliance with the License. +%%% You may obtain a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, software +%%% distributed under the License is distributed on an "AS IS" BASIS, +%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%%% See the License for the specific language governing permissions and +%%% limitations under the License. +%%%=================================================================== -module(emqx_connection). @@ -49,7 +49,7 @@ %% Unused fields: connname, peerhost, peerport -record(state, {connection, peername, conn_state, await_recv, - rate_limit, packet_size, parser, proto_state, + rate_limit, max_packet_size, proto_state, parse_state, keepalive, enable_stats, idle_timeout, force_gc_count}). -define(INFO_KEYS, [peername, conn_state, await_recv]). @@ -109,24 +109,22 @@ do_init(Conn, Env, Peername) -> SendFun = send_fun(Conn, Peername), RateLimit = get_value(rate_limit, Conn:opts()), PacketSize = get_value(max_packet_size, Env, ?MAX_PACKET_SIZE), - Parser = emqx_parser:initial_state(PacketSize), ProtoState = emqx_protocol:init(Conn, Peername, SendFun, Env), EnableStats = get_value(client_enable_stats, Env, false), IdleTimout = get_value(client_idle_timeout, Env, 30000), ForceGcCount = emqx_gc:conn_max_gc_count(), - State = run_socket(#state{connection = Conn, - peername = Peername, - await_recv = false, - conn_state = running, - rate_limit = RateLimit, - packet_size = PacketSize, - parser = Parser, - proto_state = ProtoState, - enable_stats = EnableStats, - idle_timeout = IdleTimout, - force_gc_count = ForceGcCount}), + State = run_socket(#state{connection = Conn, + peername = Peername, + await_recv = false, + conn_state = running, + rate_limit = RateLimit, + max_packet_size = PacketSize, + proto_state = ProtoState, + enable_stats = EnableStats, + idle_timeout = IdleTimout, + force_gc_count = ForceGcCount}), gen_server:enter_loop(?MODULE, [{hibernate_after, 10000}], - State, self(), IdleTimout). + init_parse_state(State), self(), IdleTimout). send_fun(Conn, Peername) -> Self = self(), @@ -143,6 +141,11 @@ send_fun(Conn, Peername) -> end end. +init_parse_state(State = #state{max_packet_size = Size, proto_state = ProtoState}) -> + emqx_parser:initial_state([{max_len, Size}, + {ver, emqx_protocol:get(proto_ver, ProtoState)}]), + State. + handle_pre_hibernate(State) -> {hibernate, emqx_gc:reset_conn_gc_count(#state.force_gc_count, emit_stats(State))}. @@ -308,19 +311,17 @@ code_change(_OldVsn, State, _Extra) -> received(<<>>, State) -> {noreply, gc(State)}; -received(Bytes, State = #state{parser = Parser, - packet_size = PacketSize, +received(Bytes, State = #state{parse_state = ParseState, proto_state = ProtoState, idle_timeout = IdleTimeout}) -> - case catch emqx_parser:parse(Bytes, Parser) of - {more, NewParser} -> - {noreply, run_socket(State#state{parser = NewParser}), IdleTimeout}; + case catch emqx_parser:parse(Bytes, ParseState) of + {more, NewParseState} -> + {noreply, State#state{parse_state = NewParseState}, IdleTimeout}; {ok, Packet, Rest} -> emqx_metrics:received(Packet), case emqx_protocol:received(Packet, ProtoState) of {ok, ProtoState1} -> - received(Rest, State#state{parser = emqx_parser:initial_state(PacketSize), - proto_state = ProtoState1}); + received(Rest, init_parse_state(State#state{proto_state = ProtoState1})); {error, Error} -> ?LOG(error, "Protocol error - ~p", [Error], State), shutdown(Error, State); diff --git a/src/emqx_mod_subscription.erl b/src/emqx_mod_subscription.erl index c6d6dd554..d7669b274 100644 --- a/src/emqx_mod_subscription.erl +++ b/src/emqx_mod_subscription.erl @@ -33,10 +33,10 @@ load(Topics) -> emqx:hook('client.connected', fun ?MODULE:on_client_connected/3, [Topics]). -on_client_connected(?CONNACK_ACCEPT, Client = #client{client_id = ClientId, - client_pid = ClientPid, - username = Username}, Topics) -> - +on_client_connected(RC, Client = #client{client_id = ClientId, + client_pid = ClientPid, + username = Username}, Topics) + when RC < 16#80 -> Replace = fun(Topic) -> rep(<<"%u">>, Username, rep(<<"%c">>, ClientId, Topic)) end, TopicTable = [{Replace(Topic), Qos} || {Topic, Qos} <- Topics], ClientPid ! {subscribe, TopicTable}, diff --git a/src/emqx_mqtt_properties.erl b/src/emqx_mqtt_properties.erl index 5df1569c6..8ef559a37 100644 --- a/src/emqx_mqtt_properties.erl +++ b/src/emqx_mqtt_properties.erl @@ -16,71 +16,67 @@ -module(emqx_mqtt_properties). --export([name/1, id/1, validate/1]). +-include("emqx_mqtt.hrl"). -%%-------------------------------------------------------------------- -%% Property id to name -%%-------------------------------------------------------------------- +-export([id/1, name/1, filter/2, validate/1]). + +-define(PROPS_TABLE, + #{16#01 => {'Payload-Format-Indicator', 'Byte', [?PUBLISH]}, + 16#02 => {'Message-Expiry-Interval', 'Four-Byte-Integer', [?PUBLISH]}, + 16#03 => {'Content-Type', 'UTF8-Encoded-String', [?PUBLISH]}, + 16#08 => {'Response-Topic', 'UTF8-Encoded-String', [?PUBLISH]}, + 16#09 => {'Correlation-Data', 'Binary-Data', [?PUBLISH]}, + 16#0B => {'Subscription-Identifier', 'Variable-Byte-Integer', [?PUBLISH, ?SUBSCRIBE]}, + 16#11 => {'Session-Expiry-Interval', 'Four-Byte-Integer', [?CONNECT, ?CONNACK, ?DISCONNECT]}, + 16#12 => {'Assigned-Client-Identifier', 'UTF8-Encoded-String', [?CONNACK]}, + 16#13 => {'Server-Keep-Alive', 'Two-Byte-Integer', [?CONNACK]}, + 16#15 => {'Authentication-Method', 'UTF8-Encoded-String', [?CONNECT, ?CONNACK, ?AUTH]}, + 16#16 => {'Authentication-Data', 'Binary-Data', [?CONNECT, ?CONNACK, ?AUTH]}, + 16#17 => {'Request-Problem-Information', 'Byte', [?CONNECT]}, + 16#18 => {'Will-Delay-Interval', 'Four-Byte-Integer', ['WILL']}, + 16#19 => {'Request-Response-Information', 'Byte', [?CONNECT]}, + 16#1A => {'Response-Information', 'UTF8-Encoded-String', [?CONNACK]}, + 16#1C => {'Server-Reference', 'UTF8-Encoded-String', [?CONNACK, ?DISCONNECT]}, + 16#1F => {'Reason-String', 'UTF8-Encoded-String', 'ALL'}, + 16#21 => {'Receive-Maximum', 'Two-Byte-Integer', [?CONNECT, ?CONNACK]}, + 16#22 => {'Topic-Alias-Maximum', 'Two-Byte-Integer', [?CONNECT, ?CONNACK]}, + 16#23 => {'Topic-Alias', 'Two-Byte-Integer', [?PUBLISH]}, + 16#24 => {'Maximum-QoS', 'Byte', [?CONNACK]}, + 16#25 => {'Retain-Available', 'Byte', [?CONNACK]}, + 16#26 => {'User-Property', 'UTF8-String-Pair', 'ALL'}, + 16#27 => {'Maximum-Packet-Size', 'Four-Byte-Integer', [?CONNECT, ?CONNACK]}, + 16#28 => {'Wildcard-Subscription-Available', 'Byte', [?CONNACK]}, + 16#29 => {'Subscription-Identifier-Available', 'Byte', [?CONNACK]}, + 16#2A => {'Shared-Subscription-Available', 'Byte', [?CONNACK]}}). -%% 01: Byte; PUBLISH, Will Properties name(16#01) -> 'Payload-Format-Indicator'; -%% 02: Four Byte Integer; PUBLISH, Will Properties name(16#02) -> 'Message-Expiry-Interval'; -%% 03: UTF-8 Encoded String; PUBLISH, Will Properties name(16#03) -> 'Content-Type'; -%% 08: UTF-8 Encoded String; PUBLISH, Will Properties name(16#08) -> 'Response-Topic'; -%% 09: Binary Data; PUBLISH, Will Properties name(16#09) -> 'Correlation-Data'; -%% 11: Variable Byte Integer; PUBLISH, SUBSCRIBE name(16#0B) -> 'Subscription-Identifier'; -%% 17: Four Byte Integer; CONNECT, CONNACK, DISCONNECT name(16#11) -> 'Session-Expiry-Interval'; -%% 18: UTF-8 Encoded String; CONNACK name(16#12) -> 'Assigned-Client-Identifier'; -%% 19: Two Byte Integer; CONNACK name(16#13) -> 'Server-Keep-Alive'; -%% 21: UTF-8 Encoded String; CONNECT, CONNACK, AUTH name(16#15) -> 'Authentication-Method'; -%% 22: Binary Data; CONNECT, CONNACK, AUTH name(16#16) -> 'Authentication-Data'; -%% 23: Byte; CONNECT name(16#17) -> 'Request-Problem-Information'; -%% 24: Four Byte Integer; Will Properties name(16#18) -> 'Will-Delay-Interval'; -%% 25: Byte; CONNECT name(16#19) -> 'Request-Response-Information'; -%% 26: UTF-8 Encoded String; CONNACK -name(16#1A) -> 'Response Information'; -%% 28: UTF-8 Encoded String; CONNACK, DISCONNECT +name(16#1A) -> 'Response-Information'; name(16#1C) -> 'Server-Reference'; -%% 31: UTF-8 Encoded String; CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT, AUTH name(16#1F) -> 'Reason-String'; -%% 33: Two Byte Integer; CONNECT, CONNACK name(16#21) -> 'Receive-Maximum'; -%% 34: Two Byte Integer; CONNECT, CONNACK name(16#22) -> 'Topic-Alias-Maximum'; -%% 35: Two Byte Integer; PUBLISH -name(16#23) -> 'Topic Alias'; -%% 36: Byte; CONNACK +name(16#23) -> 'Topic-Alias'; name(16#24) -> 'Maximum-QoS'; -%% 37: Byte; CONNACK name(16#25) -> 'Retain-Available'; -%% 38: UTF-8 String Pair; ALL name(16#26) -> 'User-Property'; -%% 39: Four Byte Integer; CONNECT, CONNACK name(16#27) -> 'Maximum-Packet-Size'; -%% 40: Byte; CONNACK name(16#28) -> 'Wildcard-Subscription-Available'; -%% 41: Byte; CONNACK name(16#29) -> 'Subscription-Identifier-Available'; -%% 42: Byte; CONNACK name(16#2A) -> 'Shared-Subscription-Available'. -%%-------------------------------------------------------------------- -%% Property name to id -%%-------------------------------------------------------------------- - id('Payload-Format-Indicator') -> 16#01; id('Message-Expiry-Interval') -> 16#02; id('Content-Type') -> 16#03; @@ -91,16 +87,16 @@ id('Session-Expiry-Interval') -> 16#11; id('Assigned-Client-Identifier') -> 16#12; id('Server-Keep-Alive') -> 16#13; id('Authentication-Method') -> 16#15; -id('Authentication Data') -> 16#16; +id('Authentication-Data') -> 16#16; id('Request-Problem-Information') -> 16#17; id('Will-Delay-Interval') -> 16#18; id('Request-Response-Information') -> 16#19; -id('Response Information') -> 16#1A; +id('Response-Information') -> 16#1A; id('Server-Reference') -> 16#1C; id('Reason-String') -> 16#1F; id('Receive-Maximum') -> 16#21; id('Topic-Alias-Maximum') -> 16#22; -id('Topic Alias') -> 16#23; +id('Topic-Alias') -> 16#23; id('Maximum-QoS') -> 16#24; id('Retain-Available') -> 16#25; id('User-Property') -> 16#26; @@ -109,5 +105,42 @@ id('Wildcard-Subscription-Available') -> 16#28; id('Subscription-Identifier-Available') -> 16#29; id('Shared-Subscription-Available') -> 16#2A. -%%TODO: -validate(Props) when is_list(Props) -> ok. +filter(Packet, Props) when ?CONNECT =< Packet, Packet =< ?AUTH -> + Fun = fun(Name) -> + case maps:find(id(Name), ?PROPS_TABLE) of + {ok, {Name, _Type, 'ALL'}} -> + true; + {ok, {Name, _Type, Packets}} -> + lists:member(Packet, Packets); + error -> false + end + end, + [Prop || Prop = {Name, _} <- Props, Fun(Name)]. + +validate(Props) when is_map(Props) -> + lists:foreach(fun validate_prop/1, maps:to_list(Props)). + +validate_prop(Prop = {Name, Val}) -> + case maps:find(id(Name), ?PROPS_TABLE) of + {ok, {Name, Type, _}} -> + validate_value(Type, Val) + orelse error(bad_property, Prop); + error -> + error({bad_property, Prop}) + end. + +validate_value('Byte', Val) -> + is_integer(Val); +validate_value('Two-Byte-Integer', Val) -> + is_integer(Val); +validate_value('Four-Byte-Integer', Val) -> + is_integer(Val); +validate_value('Variable-Byte-Integer', Val) -> + is_integer(Val); +validate_value('UTF8-Encoded-String', Val) -> + is_binary(Val); +validate_value('Binary-Data', Val) -> + is_binary(Val); +validate_value('User-Property', Val) -> + is_tuple(Val) orelse is_list(Val). + diff --git a/src/emqx_mqtt_rscode.erl b/src/emqx_mqtt_rscode.erl deleted file mode 100644 index 5bc7c0210..000000000 --- a/src/emqx_mqtt_rscode.erl +++ /dev/null @@ -1,115 +0,0 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%%-------------------------------------------------------------------- - --module(emqx_mqtt_rscode). - --export([value/1]). - -%%-------------------------------------------------------------------- -%% Reason code to name -%%-------------------------------------------------------------------- - -%% 00: Success; CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH -value('Success') -> 16#00; -%% 00: Normal disconnection; DISCONNECT -value('Normal-Disconnection') -> 16#00; -%% 00: Granted QoS 0; SUBACK -value('Granted-QoS0') -> 16#00; -%% 01: Granted QoS 1; SUBACK -value('Granted-QoS1') -> 16#01; -%% 02: Granted QoS 2; SUBACK -value('Granted-QoS2') -> 16#02; -%% 04: Disconnect with Will Message; DISCONNECT -value('Disconnect-With-Will-Message') -> 16#04; -%% 16: No matching subscribers; PUBACK, PUBREC -value('No-Matching-Subscribers') -> 16#10; -%% 17: No subscription existed; UNSUBACK -value('No-Subscription-Existed') -> 16#11; -%% 24: Continue authentication; AUTH -value('Continue-Authentication') -> 16#18; -%% 25: Re-Authenticate; AUTH -value('Re-Authenticate') -> 16#19; -%% 128: Unspecified error; CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT -value('Unspecified-Error') -> 16#80; -%% 129: Malformed Packet; CONNACK, DISCONNECT -value('Malformed-Packet') -> 16#81; -%% 130: Protocol Error; CONNACK, DISCONNECT -value('Protocol-Error') -> 16#82; -%% 131: Implementation specific error; CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT -value('Implementation-Specific-Error') -> 16#83; -%% 132: Unsupported Protocol Version; CONNACK -value('Unsupported-Protocol-Version') -> 16#84; -%% 133: Client Identifier not valid; CONNACK -value('Client-Identifier-not-Valid') -> 16#85; -%% 134: Bad User Name or Password; CONNACK -value('Bad-Username-or-Password') -> 16#86; -%% 135: Not authorized; CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT -value('Not-Authorized') -> 16#87; -%% 136: Server unavailable; CONNACK -value('Server-Unavailable') -> 16#88; -%% 137: Server busy; CONNACK, DISCONNECT -value('Server-Busy') -> 16#89; -%% 138: Banned; CONNACK -value('Banned') -> 16#8A; -%% 139: Server shutting down; DISCONNECT -value('Server-Shutting-Down') -> 16#8B; -%% 140: Bad authentication method; CONNACK, DISCONNECT -value('Bad-Authentication-Method') -> 16#8C; -%% 141: Keep Alive timeout; DISCONNECT -value('Keep-Alive-Timeout') -> 16#8D; -%% 142: Session taken over; DISCONNECT -value('Session-Taken-Over') -> 16#8E; -%% 143: Topic Filter invalid; SUBACK, UNSUBACK, DISCONNECT -value('Topic-Filter-Invalid') -> 16#8F; -%% 144: Topic Name invalid; CONNACK, PUBACK, PUBREC, DISCONNECT -value('Topic-Name-Invalid') -> 16#90; -%% 145: Packet Identifier in use; PUBACK, PUBREC, SUBACK, UNSUBACK -value('Packet-Identifier-Inuse') -> 16#91; -%% 146: Packet Identifier not found; PUBREL, PUBCOMP -value('Packet-Identifier-Not-Found') -> 16#92; -%% 147: Receive Maximum exceeded; DISCONNECT -value('Receive-Maximum-Exceeded') -> 16#93; -%% 148: Topic Alias invalid; DISCONNECT -value('Topic-Alias-Invalid') -> 16#94; -%% 149: Packet too large; CONNACK, DISCONNECT -value('Packet-Too-Large') -> 16#95; -%% 150: Message rate too high; DISCONNECT -value('Message-Rate-Too-High') -> 16#96; -%% 151: Quota exceeded; CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT -value('Quota-Exceeded') -> 16#97; -%% 152: Administrative action; DISCONNECT -value('Administrative-Action') -> 16#98; -%% 153: Payload format invalid; CONNACK, PUBACK, PUBREC, DISCONNECT -value('Payload-Format-Invalid') -> 16#99; -%% 154: Retain not supported; CONNACK, DISCONNECT -value('Retain-Not-Supported') -> 16#9A; -%% 155: QoS not supported; CONNACK, DISCONNECT -value('QoS-Not-Supported') -> 16#9B; -%% 156: Use another server; CONNACK, DISCONNECT -value('Use-Another-Server') -> 16#9C; -%% 157: Server moved; CONNACK, DISCONNECT -value('Server-Moved') -> 16#9D; -%% 158: Shared Subscriptions not supported; SUBACK, DISCONNECT -value('Shared-Subscriptions-Not-Supported') -> 16#9E; -%% 159: Connection rate exceeded; CONNACK, DISCONNECT -value('Connection-Rate-Exceeded') -> 16#9F; -%% 160: Maximum connect time; DISCONNECT -value('Maximum-Connect-Time') -> 16#A0; -%% 161: Subscription Identifiers not supported; SUBACK, DISCONNECT -value('Subscription-Identifiers-Not-Supported') -> 16#A1; -%% 162: Wildcard-Subscriptions-Not-Supported; SUBACK, DISCONNECT -value('Wildcard-Subscriptions-Not-Supported') -> 16#A2. - diff --git a/src/emqx_packet.erl b/src/emqx_packet.erl index fc23fb883..655bdd504 100644 --- a/src/emqx_packet.erl +++ b/src/emqx_packet.erl @@ -20,14 +20,14 @@ -include("emqx_mqtt.hrl"). --export([protocol_name/1, type_name/1, connack_error/1]). +-export([protocol_name/1, type_name/1]). -export([format/1]). -export([to_message/1, from_message/1]). %% @doc Protocol name of version --spec(protocol_name(mqtt_vsn()) -> binary()). +-spec(protocol_name(mqtt_version()) -> binary()). protocol_name(?MQTT_PROTO_V3) -> <<"MQIsdp">>; protocol_name(?MQTT_PROTO_V4) -> <<"MQTT">>; protocol_name(?MQTT_PROTO_V5) -> <<"MQTT">>. @@ -37,16 +37,6 @@ protocol_name(?MQTT_PROTO_V5) -> <<"MQTT">>. type_name(Type) when Type > ?RESERVED andalso Type =< ?AUTH -> lists:nth(Type, ?TYPE_NAMES). -%% @doc Connack Error --spec(connack_error(mqtt_connack()) -> atom()). -connack_error(?CONNACK_ACCEPT) -> 'CONNACK_ACCEPT'; -connack_error(?CONNACK_PROTO_VER) -> 'CONNACK_PROTO_VER'; -connack_error(?CONNACK_INVALID_ID) -> 'CONNACK_INVALID_ID'; -connack_error(?CONNACK_SERVER) -> 'CONNACK_SERVER'; -connack_error(?CONNACK_CREDENTIALS) -> 'CONNACK_CREDENTIALS'; -connack_error(?CONNACK_AUTH) -> 'CONNACK_AUTH'; -connack_error(_ReasonCode) -> 'CONNACK_UNKNOWN_ERR'. - %% @doc From Message to Packet -spec(from_message(message()) -> mqtt_packet()). from_message(Msg = #message{qos = Qos, @@ -68,7 +58,7 @@ from_message(Msg = #message{qos = Qos, to_message(#mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH, retain = Retain, qos = Qos, - dup = Dup}, + dup = Dup}, variable = #mqtt_packet_publish{topic_name = Topic, packet_id = PacketId, properties = Props}, @@ -80,11 +70,11 @@ to_message(#mqtt_packet{header = #mqtt_packet_header{type = ?PUBLISH, properties = Props}; to_message(#mqtt_packet_connect{will_flag = false}) -> undefined; -to_message(#mqtt_packet_connect{will_retain = Retain, - will_qos = Qos, - will_topic = Topic, - will_props = Props, - will_msg = Payload}) -> +to_message(#mqtt_packet_connect{will_retain = Retain, + will_qos = Qos, + will_topic = Topic, + will_props = Props, + will_payload = Payload}) -> Msg = emqx_message:make(undefined, Topic, Payload), Msg#message{flags = #{retain => Retain}, headers = #{qos => Qos}, @@ -99,7 +89,7 @@ format_header(#mqtt_packet_header{type = Type, dup = Dup, qos = QoS, retain = Retain}, S) -> - S1 = if + S1 = if S == undefined -> <<>>; true -> [", ", S] end, @@ -113,23 +103,23 @@ format_variable(Variable, Payload) -> io_lib:format("~s, Payload=~p", [format_variable(Variable), Payload]). format_variable(#mqtt_packet_connect{ - proto_ver = ProtoVer, - proto_name = ProtoName, - will_retain = WillRetain, - will_qos = WillQoS, - will_flag = WillFlag, - clean_sess = CleanSess, - keep_alive = KeepAlive, - client_id = ClientId, - will_topic = WillTopic, - will_msg = WillMsg, - username = Username, - password = Password}) -> - Format = "ClientId=~s, ProtoName=~s, ProtoVsn=~p, CleanSess=~s, KeepAlive=~p, Username=~s, Password=~s", - Args = [ClientId, ProtoName, ProtoVer, CleanSess, KeepAlive, Username, format_password(Password)], - {Format1, Args1} = if - WillFlag -> { Format ++ ", Will(Q~p, R~p, Topic=~s, Msg=~s)", - Args ++ [WillQoS, i(WillRetain), WillTopic, WillMsg] }; + proto_ver = ProtoVer, + proto_name = ProtoName, + will_retain = WillRetain, + will_qos = WillQoS, + will_flag = WillFlag, + clean_start = CleanStart, + keepalive = KeepAlive, + client_id = ClientId, + will_topic = WillTopic, + will_payload = WillPayload, + username = Username, + password = Password}) -> + Format = "ClientId=~s, ProtoName=~s, ProtoVsn=~p, CleanStart=~s, KeepAlive=~p, Username=~s, Password=~s", + Args = [ClientId, ProtoName, ProtoVer, CleanStart, KeepAlive, Username, format_password(Password)], + {Format1, Args1} = if + WillFlag -> { Format ++ ", Will(Q~p, R~p, Topic=~s, Payload=~p)", + Args ++ [WillQoS, i(WillRetain), WillTopic, WillPayload] }; true -> {Format, Args} end, io_lib:format(Format1, Args1); @@ -149,9 +139,9 @@ format_variable(#mqtt_packet_subscribe{packet_id = PacketId, topic_filters = TopicFilters}) -> io_lib:format("PacketId=~p, TopicFilters=~p", [PacketId, TopicFilters]); -format_variable(#mqtt_packet_unsubscribe{packet_id = PacketId, - topics = Topics}) -> - io_lib:format("PacketId=~p, Topics=~p", [PacketId, Topics]); +format_variable(#mqtt_packet_unsubscribe{packet_id = PacketId, + topic_filters = Topics}) -> + io_lib:format("PacketId=~p, TopicFilters=~p", [PacketId, Topics]); format_variable(#mqtt_packet_suback{packet_id = PacketId, reason_codes = ReasonCodes}) -> diff --git a/src/emqx_parser.erl b/src/emqx_parser.erl index 5cb9aa20a..a7c6707f3 100644 --- a/src/emqx_parser.erl +++ b/src/emqx_parser.erl @@ -20,180 +20,198 @@ -include("emqx_mqtt.hrl"). -%% API -export([initial_state/0, initial_state/1, parse/2]). -type(max_packet_size() :: 1..?MAX_PACKET_SIZE). --type(state() :: #{maxlen := max_packet_size(), vsn := mqtt_vsn()}). +-type(option() :: {max_len, max_packet_size()} + | {version, mqtt_version()}). --spec(initial_state() -> {none, state()}). -initial_state() -> - initial_state(?MAX_PACKET_SIZE). +-type(state() :: {none, map()} | {more, fun()}). + +-export_type([option/0, state/0]). %% @doc Initialize a parser --spec(initial_state(max_packet_size()) -> {none, state()}). -initial_state(MaxSize) -> - {none, #{maxlen => MaxSize, vsn => ?MQTT_PROTO_V4}}. +-spec(initial_state() -> {none, map()}). +initial_state() -> initial_state([]). + +-spec(initial_state([option()]) -> {none, map()}). +initial_state(Options) when is_list(Options) -> + {none, parse_opt(Options, #{max_len => ?MAX_PACKET_SIZE, + version => ?MQTT_PROTO_V4})}. + +parse_opt([], Map) -> + Map; +parse_opt([{version, Ver}|Opts], Map) -> + parse_opt(Opts, Map#{version := Ver}); +parse_opt([{max_len, Len}|Opts], Map) -> + parse_opt(Opts, Map#{max_len := Len}); +parse_opt([_|Opts], Map) -> + parse_opt(Opts, Map). %% @doc Parse MQTT Packet --spec(parse(binary(), {none, state()} | fun()) - -> {ok, mqtt_packet()} | {error, term()} | {more, fun()}). -parse(<<>>, {none, State}) -> - {more, fun(Bin) -> parse(Bin, {none, State}) end}; -parse(<>, {none, State}) -> +-spec(parse(binary(), {none, map()} | fun()) + -> {ok, mqtt_packet()} | {error, term()} | {more, fun()}). +parse(<<>>, {none, Options}) -> + {more, fun(Bin) -> parse(Bin, {none, Options}) end}; +parse(<>, {none, Options}) -> parse_remaining_len(Rest, #mqtt_packet_header{type = Type, dup = bool(Dup), qos = fixqos(Type, QoS), - retain = bool(Retain)}, State); + retain = bool(Retain)}, Options); parse(Bin, Cont) -> Cont(Bin). -parse_remaining_len(<<>>, Header, State) -> - {more, fun(Bin) -> parse_remaining_len(Bin, Header, State) end}; -parse_remaining_len(Rest, Header, State) -> - parse_remaining_len(Rest, Header, 1, 0, State). +parse_remaining_len(<<>>, Header, Options) -> + {more, fun(Bin) -> parse_remaining_len(Bin, Header, Options) end}; +parse_remaining_len(Rest, Header, Options) -> + parse_remaining_len(Rest, Header, 1, 0, Options). -parse_remaining_len(_Bin, _Header, _Multiplier, Length, #{maxlen := MaxLen}) +parse_remaining_len(_Bin, _Header, _Multiplier, Length, #{max_len := MaxLen}) when Length > MaxLen -> - {error, invalid_mqtt_frame_len}; -parse_remaining_len(<<>>, Header, Multiplier, Length, State) -> - {more, fun(Bin) -> parse_remaining_len(Bin, Header, Multiplier, Length, State) end}; + {error, mqtt_frame_too_long}; +parse_remaining_len(<<>>, Header, Multiplier, Length, Options) -> + {more, fun(Bin) -> parse_remaining_len(Bin, Header, Multiplier, Length, Options) end}; %% Optimize: match PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK... -parse_remaining_len(<<0:1, 2:7, Rest/binary>>, Header, 1, 0, State) -> - parse_frame(Rest, Header, 2, State); +parse_remaining_len(<<0:1, 2:7, Rest/binary>>, Header, 1, 0, Options) -> + parse_frame(Rest, Header, 2, Options); %% optimize: match PINGREQ... -parse_remaining_len(<<0:8, Rest/binary>>, Header, 1, 0, State) -> - parse_frame(Rest, Header, 0, State); -parse_remaining_len(<<1:1, Len:7, Rest/binary>>, Header, Multiplier, Value, State) -> - parse_remaining_len(Rest, Header, Multiplier * ?HIGHBIT, Value + Len * Multiplier, State); -parse_remaining_len(<<0:1, Len:7, Rest/binary>>, Header, Multiplier, Value, State = #{maxlen := MaxLen}) -> +parse_remaining_len(<<0:8, Rest/binary>>, Header, 1, 0, Options) -> + parse_frame(Rest, Header, 0, Options); +parse_remaining_len(<<1:1, Len:7, Rest/binary>>, Header, Multiplier, Value, Options) -> + parse_remaining_len(Rest, Header, Multiplier * ?HIGHBIT, Value + Len * Multiplier, Options); +parse_remaining_len(<<0:1, Len:7, Rest/binary>>, Header, Multiplier, Value, + Options = #{max_len := MaxLen}) -> FrameLen = Value + Len * Multiplier, if - FrameLen > MaxLen -> {error, invalid_mqtt_frame_len}; - true -> parse_frame(Rest, Header, FrameLen, State) + FrameLen > MaxLen -> error(mqtt_frame_too_long); + true -> parse_frame(Rest, Header, FrameLen, Options) end. -parse_frame(Bin, #mqtt_packet_header{type = Type, qos = Qos} = Header, Length, State = #{vsn := Vsn}) -> - case {Type, Bin} of - {?CONNECT, <>} -> - {ProtoName, Rest1} = parse_utf(FrameBin), - %% Fix mosquitto bridge: 0x83, 0x84 - <> = Rest1, - <> = Rest2, - {Properties, Rest4} = parse_properties(ProtoVer, Rest3), - {ClientId, Rest5} = parse_utf(Rest4), - {WillProps, Rest6} = parse_will_props(Rest5, ProtoVer, WillFlag), - {WillTopic, Rest7} = parse_utf(Rest6, WillFlag), - {WillMsg, Rest8} = parse_msg(Rest7, WillFlag), - {UserName, Rest9} = parse_utf(Rest8, UsernameFlag), - {PasssWord, <<>>} = parse_utf(Rest9, PasswordFlag), - case protocol_name_approved(ProtoVer, ProtoName) of - true -> - wrap(Header, - #mqtt_packet_connect{ - proto_ver = ProtoVer, - proto_name = ProtoName, - will_retain = bool(WillRetain), - will_qos = WillQos, - will_flag = bool(WillFlag), - clean_sess = bool(CleanSess), - keep_alive = KeepAlive, - client_id = ClientId, - will_props = WillProps, - will_topic = WillTopic, - will_msg = WillMsg, - username = UserName, - password = PasssWord, - is_bridge = (BridgeTag =:= 8), - properties = Properties}, Rest); - false -> - {error, protocol_header_corrupt} +parse_frame(Bin, Header, 0, _Options) -> + wrap(Header, Bin); + +parse_frame(Bin, Header, Length, Options) -> + case Bin of + <> -> + case parse_packet(Header, FrameBin, Options) of + {Variable, Payload} -> + wrap(Header, Variable, Payload, Rest); + Variable -> + wrap(Header, Variable, Rest) end; - {?CONNACK, <>} -> - <<_Reserved:7, SP:1, ReasonCode:8>> = FrameBin, - wrap(Header, #mqtt_packet_connack{ack_flags = SP, - reason_code = ReasonCode}, Rest); - {?PUBLISH, <>} -> - {TopicName, Rest1} = parse_utf(FrameBin), - {PacketId, Rest2} = case Qos of - 0 -> {undefined, Rest1}; - _ -> <> = Rest1, - {Id, R} - end, - {Properties, Payload} = parse_properties(Vsn, Rest2), - wrap(fixdup(Header), #mqtt_packet_publish{topic_name = TopicName, - packet_id = PacketId, - properties = Properties}, - Payload, Rest); - {PubAck, <>} - when PubAck == ?PUBACK; PubAck == ?PUBREC; PubAck == ?PUBREL; PubAck == ?PUBCOMP -> - <> = FrameBin, - case Vsn == ?MQTT_PROTO_V5 of - true -> - <> = Rest1, - {Properties, Rest3} = parse_properties(Vsn, Rest2), - wrap(Header, #mqtt_packet_puback{packet_id = PacketId, - reason_code = ReasonCode, - properties = Properties}, Rest3); - false -> - wrap(Header, #mqtt_packet_puback{packet_id = PacketId}, Rest) - end; - {?SUBSCRIBE, <>} -> - %% 1 = Qos, - <> = FrameBin, - {Properties, Rest2} = parse_properties(Vsn, Rest1), - TopicFilters = parse_topics(?SUBSCRIBE, Rest2, []), - wrap(Header, #mqtt_packet_subscribe{packet_id = PacketId, - properties = Properties, - topic_filters = TopicFilters}, Rest); - {?SUBACK, <>} -> - <> = FrameBin, - {Properties, Rest2} = parse_properties(Vsn, Rest1), - wrap(Header, #mqtt_packet_suback{packet_id = PacketId, properties = Properties, - reason_codes = parse_qos(Rest2, [])}, Rest); - {?UNSUBSCRIBE, <>} -> - %% 1 = Qos, - <> = FrameBin, - {Properties, Rest2} = parse_properties(Vsn, Rest1), - Topics = parse_topics(?UNSUBSCRIBE, Rest2, []), - wrap(Header, #mqtt_packet_unsubscribe{packet_id = PacketId, - properties = Properties, - topics = Topics}, Rest); - {?UNSUBACK, <>} -> - <> = FrameBin, - {Properties, _Rest2} = parse_properties(Vsn, Rest1), - wrap(Header, #mqtt_packet_unsuback{packet_id = PacketId, - properties = Properties}, Rest); - {?PINGREQ, Rest} -> - Length = 0, - wrap(Header, Rest); - {?PINGRESP, Rest} -> - Length = 0, - wrap(Header, Rest); - {?DISCONNECT, <>} -> - if - Vsn == ?MQTT_PROTO_V5 -> - <> = FrameBin, - {Properties, Rest2} = parse_properties(Vsn, Rest1), - wrap(Header, #mqtt_packet_disconnect{reason_code = ReasonCode, - properties = Properties}, Rest2); - true -> - Length = 0, wrap(Header, Rest) - end; - {_, TooShortBin} -> + TooShortBin -> {more, fun(BinMore) -> - parse_frame(<>, Header, Length, State) + parse_frame(<>, Header, Length, Options) end} end. +parse_packet(#mqtt_packet_header{type = ?CONNECT}, FrameBin, _Options) -> + {ProtoName, Rest} = parse_utf8_string(FrameBin), + <> = Rest, + <> = Rest1, + case protocol_name_approved(ProtoVer, ProtoName) of + true -> ok; + false -> error(protocol_name_unapproved) + end, + {Properties, Rest3} = parse_properties(Rest2, ProtoVer), + {ClientId, Rest4} = parse_utf8_string(Rest3), + ConnPacket = #mqtt_packet_connect{proto_name = ProtoName, + proto_ver = ProtoVer, + is_bridge = (BridgeTag =:= 8), + clean_start = bool(CleanStart), + will_flag = bool(WillFlag), + will_qos = WillQos, + will_retain = bool(WillRetain), + keepalive = KeepAlive, + properties = Properties, + client_id = ClientId}, + {ConnPacket1, Rest5} = parse_will_message(ConnPacket, Rest4), + {Username, Rest6} = parse_utf8_string(Rest5, bool(UsernameFlag)), + {Passsword, <<>>} = parse_utf8_string(Rest6, bool(PasswordFlag)), + ConnPacket1#mqtt_packet_connect{username = Username, password = Passsword}; + +parse_packet(#mqtt_packet_header{type = ?CONNACK}, + <>, #{version := Ver}) -> + {Properties, <<>>} = parse_properties(Rest, Ver), + #mqtt_packet_connack{ack_flags = AckFlags, + reason_code = ReasonCode, + properties = Properties}; + +parse_packet(#mqtt_packet_header{type = ?PUBLISH, qos = QoS}, Bin, + #{version := Ver}) -> + {TopicName, Rest} = parse_utf8_string(Bin), + {PacketId, Rest1} = case QoS of + ?QOS_0 -> {undefined, Rest}; + _ -> parse_packet_id(Rest) + end, + {Properties, Payload} = parse_properties(Rest1, Ver), + {#mqtt_packet_publish{topic_name = TopicName, + packet_id = PacketId, + properties = Properties}, Payload}; + +parse_packet(#mqtt_packet_header{type = PubAck}, <>, _Options) + when ?PUBACK =< PubAck, PubAck =< ?PUBCOMP -> + #mqtt_packet_puback{packet_id = PacketId, reason_code = 0}; +parse_packet(#mqtt_packet_header{type = PubAck}, <>, + #{version := Ver = ?MQTT_PROTO_V5}) + when ?PUBACK =< PubAck, PubAck =< ?PUBCOMP -> + {Properties, <<>>} = parse_properties(Rest, Ver), + #mqtt_packet_puback{packet_id = PacketId, + reason_code = ReasonCode, + properties = Properties}; + +parse_packet(#mqtt_packet_header{type = ?SUBSCRIBE}, <>, + #{version := Ver}) -> + {Properties, Rest1} = parse_properties(Rest, Ver), + TopicFilters = parse_topic_filters(subscribe, Rest1), + #mqtt_packet_subscribe{packet_id = PacketId, + properties = Properties, + topic_filters = TopicFilters}; + +parse_packet(#mqtt_packet_header{type = ?SUBACK}, <>, + #{version := Ver}) -> + {Properties, Rest1} = parse_properties(Rest, Ver), + #mqtt_packet_suback{packet_id = PacketId, + properties = Properties, + reason_codes = parse_reason_codes(Rest1)}; + +parse_packet(#mqtt_packet_header{type = ?UNSUBSCRIBE}, <>, + #{version := Ver}) -> + {Properties, Rest1} = parse_properties(Rest, Ver), + TopicFilters = parse_topic_filters(unsubscribe, Rest1), + #mqtt_packet_unsubscribe{packet_id = PacketId, + properties = Properties, + topic_filters = TopicFilters}; + +parse_packet(#mqtt_packet_header{type = ?UNSUBACK}, <>, _Options) -> + #mqtt_packet_unsuback{packet_id = PacketId}; +parse_packet(#mqtt_packet_header{type = ?UNSUBACK}, <>, + #{version := Ver}) -> + {Properties, Rest1} = parse_properties(Rest, Ver), + ReasonCodes = parse_reason_codes(Rest1), + #mqtt_packet_unsuback{packet_id = PacketId, + properties = Properties, + reason_codes = ReasonCodes}; + +parse_packet(#mqtt_packet_header{type = ?DISCONNECT}, <>, + #{version := ?MQTT_PROTO_V5}) -> + {Properties, <<>>} = parse_properties(Rest, ?MQTT_PROTO_V5), + #mqtt_packet_disconnect{reason_code = ReasonCode, + properties = Properties}; + +parse_packet(#mqtt_packet_header{type = ?AUTH}, <>, + #{version := ?MQTT_PROTO_V5}) -> + {Properties, <<>>} = parse_properties(Rest, ?MQTT_PROTO_V5), + #mqtt_packet_auth{reason_code = ReasonCode, properties = Properties}. + wrap(Header, Variable, Payload, Rest) -> {ok, #mqtt_packet{header = Header, variable = Variable, payload = Payload}, Rest}. wrap(Header, Variable, Rest) -> @@ -201,111 +219,100 @@ wrap(Header, Variable, Rest) -> wrap(Header, Rest) -> {ok, #mqtt_packet{header = Header}, Rest}. -parse_will_props(Bin, ProtoVer = ?MQTT_PROTO_V5, 1) -> - parse_properties(ProtoVer, Bin); -parse_will_props(Bin, _ProtoVer, _WillFlag) -> - {#{}, Bin}. +protocol_name_approved(Ver, Name) -> + lists:member({Ver, Name}, ?PROTOCOL_NAMES). -parse_properties(?MQTT_PROTO_V5, Bin) -> +parse_will_message(Packet = #mqtt_packet_connect{will_flag = true, + proto_ver = Ver}, Bin) -> + {Props, Rest} = parse_properties(Bin, Ver), + {Topic, Rest1} = parse_utf8_string(Rest), + {Payload, Rest2} = parse_binary_data(Rest1), + {Packet#mqtt_packet_connect{will_props = Props, + will_topic = Topic, + will_payload = Payload}, Rest2}; +parse_will_message(Packet, Bin) -> + {Packet, Bin}. + +parse_packet_id(<>) -> + {PacketId, Rest}. + +parse_properties(Bin, Ver) when Ver =/= ?MQTT_PROTO_V5 -> + {undefined, Bin}; +parse_properties(<<0, Rest/binary>>, ?MQTT_PROTO_V5) -> + {#{}, Rest}; +parse_properties(Bin, ?MQTT_PROTO_V5) -> {Len, Rest} = parse_variable_byte_integer(Bin), <> = Rest, - {parse_property(PropsBin, #{}), Rest1}; -parse_properties(_MQTT_PROTO_V3, Bin) -> - {#{}, Bin}. %% No properties. + {parse_property(PropsBin, #{}), Rest1}. parse_property(<<>>, Props) -> Props; -%% 01: 'Payload-Format-Indicator', Byte; parse_property(<<16#01, Val, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Payload-Format-Indicator' => Val}); -%% 02: 'Message-Expiry-Interval', Four Byte Integer; parse_property(<<16#02, Val:32/big, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Message-Expiry-Interval' => Val}); -%% 03: 'Content-Type', UTF-8 Encoded String; parse_property(<<16#03, Bin/binary>>, Props) -> - {Val, Rest} = parse_utf(Bin), + {Val, Rest} = parse_utf8_string(Bin), parse_property(Rest, Props#{'Content-Type' => Val}); -%% 08: 'Response-Topic', UTF-8 Encoded String; parse_property(<<16#08, Bin/binary>>, Props) -> - {Val, Rest} = parse_utf(Bin), + {Val, Rest} = parse_utf8_string(Bin), parse_property(Rest, Props#{'Response-Topic' => Val}); -%% 09: 'Correlation-Data', Binary Data; parse_property(<<16#09, Len:16/big, Val:Len/binary, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Correlation-Data' => Val}); -%% 11: 'Subscription-Identifier', Variable Byte Integer; parse_property(<<16#0B, Bin/binary>>, Props) -> {Val, Rest} = parse_variable_byte_integer(Bin), parse_property(Rest, Props#{'Subscription-Identifier' => Val}); -%% 17: 'Session-Expiry-Interval', Four Byte Integer; parse_property(<<16#11, Val:32/big, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Session-Expiry-Interval' => Val}); -%% 18: 'Assigned-Client-Identifier', UTF-8 Encoded String; parse_property(<<16#12, Bin/binary>>, Props) -> - {Val, Rest} = parse_utf(Bin), + {Val, Rest} = parse_utf8_string(Bin), parse_property(Rest, Props#{'Assigned-Client-Identifier' => Val}); -%% 19: 'Server-Keep-Alive', Two Byte Integer; parse_property(<<16#13, Val:16, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Server-Keep-Alive' => Val}); -%% 21: 'Authentication-Method', UTF-8 Encoded String; parse_property(<<16#15, Bin/binary>>, Props) -> - {Val, Rest} = parse_utf(Bin), + {Val, Rest} = parse_utf8_string(Bin), parse_property(Rest, Props#{'Authentication-Method' => Val}); -%% 22: 'Authentication-Data', Binary Data; parse_property(<<16#16, Len:16/big, Val:Len/binary, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Authentication-Data' => Val}); -%% 23: 'Request-Problem-Information', Byte; parse_property(<<16#17, Val, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Request-Problem-Information' => Val}); -%% 24: 'Will-Delay-Interval', Four Byte Integer; parse_property(<<16#18, Val:32, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Will-Delay-Interval' => Val}); -%% 25: 'Request-Response-Information', Byte; parse_property(<<16#19, Val, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Request-Response-Information' => Val}); -%% 26: 'Response Information', UTF-8 Encoded String; parse_property(<<16#1A, Bin/binary>>, Props) -> - {Val, Rest} = parse_utf(Bin), + {Val, Rest} = parse_utf8_string(Bin), parse_property(Rest, Props#{'Response-Information' => Val}); -%% 28: 'Server-Reference', UTF-8 Encoded String; parse_property(<<16#1C, Bin/binary>>, Props) -> - {Val, Rest} = parse_utf(Bin), + {Val, Rest} = parse_utf8_string(Bin), parse_property(Rest, Props#{'Server-Reference' => Val}); -%% 31: 'Reason-String', UTF-8 Encoded String; parse_property(<<16#1F, Bin/binary>>, Props) -> - {Val, Rest} = parse_utf(Bin), + {Val, Rest} = parse_utf8_string(Bin), parse_property(Rest, Props#{'Reason-String' => Val}); -%% 33: 'Receive-Maximum', Two Byte Integer; parse_property(<<16#21, Val:16/big, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Receive-Maximum' => Val}); -%% 34: 'Topic-Alias-Maximum', Two Byte Integer; parse_property(<<16#22, Val:16/big, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Topic-Alias-Maximum' => Val}); -%% 35: 'Topic-Alias', Two Byte Integer; parse_property(<<16#23, Val:16/big, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Topic-Alias' => Val}); -%% 36: 'Maximum-QoS', Byte; parse_property(<<16#24, Val, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Maximum-QoS' => Val}); -%% 37: 'Retain-Available', Byte; parse_property(<<16#25, Val, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Retain-Available' => Val}); -%% 38: 'User-Property', UTF-8 String Pair; parse_property(<<16#26, Bin/binary>>, Props) -> - {Pair, Rest} = parse_utf_pair(Bin), - parse_property(Rest, case maps:find('User-Property', Props) of - {ok, UserProps} -> Props#{'User-Property' := [Pair | UserProps]}; - error -> Props#{'User-Property' := [Pair]} - end); -%% 39: 'Maximum-Packet-Size', Four Byte Integer; + {Pair, Rest} = parse_utf8_pair(Bin), + case maps:find('User-Property', Props) of + {ok, UserProps} -> + parse_property(Rest,Props#{'User-Property' := [Pair|UserProps]}); + error -> + parse_property(Rest, Props#{'User-Property' => [Pair]}) + end; parse_property(<<16#27, Val:32, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Maximum-Packet-Size' => Val}); -%% 40: 'Wildcard-Subscription-Available', Byte; parse_property(<<16#28, Val, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Wildcard-Subscription-Available' => Val}); -%% 41: 'Subscription-Identifier-Available', Byte; parse_property(<<16#29, Val, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Subscription-Identifier-Available' => Val}); -%% 42: 'Shared-Subscription-Available', Byte; parse_property(<<16#2A, Val, Bin/binary>>, Props) -> parse_property(Bin, Props#{'Shared-Subscription-Available' => Val}). @@ -316,53 +323,36 @@ parse_variable_byte_integer(<<1:1, Len:7, Rest/binary>>, Multiplier, Value) -> parse_variable_byte_integer(<<0:1, Len:7, Rest/binary>>, Multiplier, Value) -> {Value + Len * Multiplier, Rest}. -parse_topics(_Packet, <<>>, Topics) -> - lists:reverse(Topics); -parse_topics(?SUBSCRIBE = Sub, Bin, Topics) -> - {Name, <<_Reserved:2, RetainHandling:2, KeepRetain:1, NoLocal:1, QoS:2, Rest/binary>>} = parse_utf(Bin), - SubOpts = [{qos, QoS}, {retain_handling, RetainHandling}, {keep_retain, KeepRetain}, {no_local, NoLocal}], - parse_topics(Sub, Rest, [{Name, SubOpts}| Topics]); -parse_topics(?UNSUBSCRIBE = Sub, Bin, Topics) -> - {Name, <>} = parse_utf(Bin), - parse_topics(Sub, Rest, [Name | Topics]). +parse_topic_filters(subscribe, Bin) -> + [{Topic, #mqtt_subopts{rh = Rh, rap = Rap, nl = Nl, qos = QoS}} + || <> <= Bin]; -parse_qos(<<>>, Acc) -> - lists:reverse(Acc); -parse_qos(<>, Acc) -> - parse_qos(Rest, [QoS | Acc]). +parse_topic_filters(unsubscribe, Bin) -> + [Topic || <> <= Bin]. -parse_utf_pair(Bin) -> +parse_reason_codes(Bin) -> + [Code || <> <= Bin]. + +parse_utf8_pair(Bin) -> [{Name, Value} || <> <= Bin]. -parse_utf(Bin, 0) -> +parse_utf8_string(Bin, false) -> {undefined, Bin}; -parse_utf(Bin, _) -> - parse_utf(Bin). +parse_utf8_string(Bin, true) -> + parse_utf8_string(Bin). -parse_utf(<>) -> +parse_utf8_string(<>) -> {Str, Rest}. -parse_msg(Bin, 0) -> - {undefined, Bin}; -parse_msg(<>, _) -> - {Msg, Rest}. +parse_binary_data(<>) -> + {Data, Rest}. bool(0) -> false; bool(1) -> true. -protocol_name_approved(Ver, Name) -> - lists:member({Ver, Name}, ?PROTOCOL_NAMES). - %% Fix Issue#575 fixqos(?PUBREL, 0) -> 1; fixqos(?SUBSCRIBE, 0) -> 1; fixqos(?UNSUBSCRIBE, 0) -> 1; fixqos(_Type, QoS) -> QoS. -%% Fix Issue#1319 -fixdup(Header = #mqtt_packet_header{qos = ?QOS0, dup = true}) -> - Header#mqtt_packet_header{dup = false}; -fixdup(Header = #mqtt_packet_header{qos = ?QOS2, dup = true}) -> - Header#mqtt_packet_header{dup = false}; -fixdup(Header) -> Header. - diff --git a/src/emqx_protocol.erl b/src/emqx_protocol.erl index f301378cf..370ab4739 100644 --- a/src/emqx_protocol.erl +++ b/src/emqx_protocol.erl @@ -25,7 +25,7 @@ -import(proplists, [get_value/2, get_value/3]). %% API --export([init/3, init/4, info/1, stats/1, clientid/1, client/1, session/1]). +-export([init/3, init/4, get/2, info/1, stats/1, clientid/1, client/1, session/1]). -export([subscribe/2, unsubscribe/2, pubrel/2, shutdown/2]). @@ -43,14 +43,14 @@ %% Protocol State %% ws_initial_headers: Headers from first HTTP request for WebSocket Client. -record(proto_state, {peername, sendfun, connected = false, client_id, client_pid, - clean_sess, proto_ver, proto_name, username, is_superuser, + clean_start, proto_ver, proto_name, username, is_superuser, will_msg, keepalive, keepalive_backoff, max_clientid_len, session, stats_data, mountpoint, ws_initial_headers, peercert_username, is_bridge, connected_at}). -type(proto_state() :: #proto_state{}). --define(INFO_KEYS, [client_id, username, clean_sess, proto_ver, proto_name, +-define(INFO_KEYS, [client_id, username, clean_start, proto_ver, proto_name, keepalive, will_msg, ws_initial_headers, mountpoint, peercert_username, connected_at]). @@ -98,6 +98,12 @@ repl_username_with_peercert(State = #proto_state{peercert_username = undefined}) repl_username_with_peercert(State = #proto_state{peercert_username = PeerCert}) -> State#proto_state{username = PeerCert}. +%%TODO:: +get(proto_ver, #proto_state{proto_ver = Ver}) -> + Ver; +get(_, _ProtoState) -> + undefined. + info(ProtoState) -> ?record_to_proplist(proto_state, ProtoState, ?INFO_KEYS). @@ -111,7 +117,7 @@ client(#proto_state{client_id = ClientId, client_pid = ClientPid, peername = Peername, username = Username, - clean_sess = CleanSess, + clean_start = CleanStart, proto_ver = ProtoVer, keepalive = Keepalive, will_msg = WillMsg, @@ -133,7 +139,7 @@ session(#proto_state{session = Session}) -> %% CONNECT – Client requests a connection to a Server -%% A Client can only send the CONNECT Packet once over a Network Connection. +%% A Client can only send the CONNECT Packet once over a Network Connection. -spec(received(mqtt_packet(), proto_state()) -> {ok, proto_state()} | {error, term()}). received(Packet = ?PACKET(?CONNECT), State = #proto_state{connected = false, stats_data = Stats}) -> @@ -188,8 +194,8 @@ process(?CONNECT_PACKET(Var), State0) -> proto_name = ProtoName, username = Username, password = Password, - clean_sess = CleanSess, - keep_alive = KeepAlive, + clean_start= CleanStart, + keepalive = KeepAlive, client_id = ClientId, is_bridge = IsBridge} = Var, @@ -198,7 +204,7 @@ process(?CONNECT_PACKET(Var), State0) -> proto_name = ProtoName, username = Username, client_id = ClientId, - clean_sess = CleanSess, + clean_start = CleanStart, keepalive = KeepAlive, will_msg = willmsg(Var, State0), is_bridge = IsBridge, @@ -206,14 +212,14 @@ process(?CONNECT_PACKET(Var), State0) -> {ReturnCode1, SessPresent, State3} = case validate_connect(Var, State1) of - ?CONNACK_ACCEPT -> + ?RC_SUCCESS -> case authenticate(client(State1), Password) of {ok, IsSuperuser} -> %% Generate clientId if null State2 = maybe_set_clientid(State1), %% Start session - case emqx_sm:open_session(#{clean_start => CleanSess, + case emqx_sm:open_session(#{clean_start => CleanStart, client_id => clientid(State2), username => Username, client_pid => self()}) of @@ -227,13 +233,13 @@ process(?CONNECT_PACKET(Var), State0) -> %% Emit Stats self() ! emit_stats, %% ACCEPT - {?CONNACK_ACCEPT, SP, State2#proto_state{session = Session, is_superuser = IsSuperuser}}; + {?RC_SUCCESS, SP, State2#proto_state{session = Session, is_superuser = IsSuperuser}}; {error, Error} -> {stop, {shutdown, Error}, State2} end; {error, Reason}-> ?LOG(error, "Username '~s' login failed for ~p", [Username, Reason], State1), - {?CONNACK_CREDENTIALS, false, State1} + {?RC_BAD_USER_NAME_OR_PASSWORD, false, State1} end; ReturnCode -> {ReturnCode, false, State1} @@ -252,19 +258,19 @@ process(Packet = ?PUBLISH_PACKET(_Qos, Topic, _PacketId, _Payload), State = #pro end, {ok, State}; -process(?PUBACK_PACKET(?PUBACK, PacketId), State = #proto_state{session = Session}) -> +process(?PUBACK_PACKET(PacketId), State = #proto_state{session = Session}) -> emqx_session:puback(Session, PacketId), {ok, State}; -process(?PUBACK_PACKET(?PUBREC, PacketId), State = #proto_state{session = Session}) -> +process(?PUBREC_PACKET(PacketId), State = #proto_state{session = Session}) -> emqx_session:pubrec(Session, PacketId), send(?PUBREL_PACKET(PacketId), State); -process(?PUBACK_PACKET(?PUBREL, PacketId), State = #proto_state{session = Session}) -> +process(?PUBREL_PACKET(PacketId), State = #proto_state{session = Session}) -> emqx_session:pubrel(Session, PacketId), - send(?PUBACK_PACKET(?PUBCOMP, PacketId), State); + send(?PUBCOMP_PACKET(PacketId), State); -process(?PUBACK_PACKET(?PUBCOMP, PacketId), State = #proto_state{session = Session})-> +process(?PUBCOMP_PACKET(PacketId), State = #proto_state{session = Session})-> emqx_session:pubcomp(Session, PacketId), {ok, State}; %% Protect from empty topic table @@ -346,7 +352,10 @@ with_puback(Type, Packet = ?PUBLISH_PACKET(_Qos, PacketId), Msg1 = Msg#message{from = #client{client_id = ClientId, username = Username}}, case emqx_session:publish(Session, mount(replvar(MountPoint, State), Msg1)) of ok -> - send(?PUBACK_PACKET(Type, PacketId), State); + case Type of + ?PUBACK -> send(?PUBACK_PACKET(PacketId), State); + ?PUBREC -> send(?PUBREC_PACKET(PacketId), State) + end; {error, Error} -> ?LOG(error, "PUBLISH ~p error: ~p", [PacketId, Error], State) end. @@ -390,11 +399,10 @@ inc_stats(Type, PktPos, PktCnt, MsgPos, MsgCnt, Stats) -> false -> Stats1 end. -stop_if_auth_failure(RC, State) when RC == ?CONNACK_CREDENTIALS; RC == ?CONNACK_AUTH -> - {stop, {shutdown, auth_failure}, State}; - -stop_if_auth_failure(_RC, State) -> - {ok, State}. +stop_if_auth_failure(?RC_SUCCESS, State) -> + {ok, State}; +stop_if_auth_failure(RC, State) when RC =/= ?RC_SUCCESS -> + {stop, {shutdown, auth_failure}, State}. shutdown(_Error, #proto_state{client_id = undefined}) -> ignore; @@ -450,15 +458,13 @@ start_keepalive(Sec, #proto_state{keepalive_backoff = Backoff}) when Sec > 0 -> validate_connect(Connect = #mqtt_packet_connect{}, ProtoState) -> case validate_protocol(Connect) of - true -> + true -> case validate_clientid(Connect, ProtoState) of - true -> - ?CONNACK_ACCEPT; - false -> - ?CONNACK_INVALID_ID + true -> ?RC_SUCCESS; + false -> ?RC_CLIENT_IDENTIFIER_NOT_VALID end; - false -> - ?CONNACK_PROTO_VER + false -> + ?RC_UNSUPPORTED_PROTOCOL_VERSION end. validate_protocol(#mqtt_packet_connect{proto_ver = Ver, proto_name = Name}) -> @@ -469,10 +475,10 @@ validate_clientid(#mqtt_packet_connect{client_id = ClientId}, when (byte_size(ClientId) >= 1) andalso (byte_size(ClientId) =< MaxLen) -> true; -%% Issue#599: Null clientId and clean_sess = false -validate_clientid(#mqtt_packet_connect{client_id = ClientId, - clean_sess = CleanSess}, _ProtoState) - when byte_size(ClientId) == 0 andalso (not CleanSess) -> +%% Issue#599: Null clientId and clean_start = false +validate_clientid(#mqtt_packet_connect{client_id = ClientId, + clean_start = CleanStart}, _ProtoState) + when byte_size(ClientId) == 0 andalso (not CleanStart) -> false; %% MQTT3.1.1 allow null clientId. @@ -481,10 +487,10 @@ validate_clientid(#mqtt_packet_connect{proto_ver =?MQTT_PROTO_V4, when byte_size(ClientId) =:= 0 -> true; -validate_clientid(#mqtt_packet_connect{proto_ver = ProtoVer, - clean_sess = CleanSess}, ProtoState) -> - ?LOG(warning, "Invalid clientId. ProtoVer: ~p, CleanSess: ~s", - [ProtoVer, CleanSess], ProtoState), +validate_clientid(#mqtt_packet_connect{proto_ver = ProtoVer, + clean_start = CleanStart}, ProtoState) -> + ?LOG(warning, "Invalid clientId. ProtoVer: ~p, CleanStart: ~s", + [ProtoVer, CleanStart], ProtoState), false. validate_packet(?PUBLISH_PACKET(_Qos, Topic, _PacketId, _Payload)) -> @@ -499,7 +505,7 @@ validate_packet(?SUBSCRIBE_PACKET(_PacketId, TopicTable)) -> validate_packet(?UNSUBSCRIBE_PACKET(_PacketId, Topics)) -> validate_topics(filter, Topics); -validate_packet(_Packet) -> +validate_packet(_Packet) -> ok. validate_topics(_Type, []) -> diff --git a/src/emqx_reason_codes.erl b/src/emqx_reason_codes.erl new file mode 100644 index 000000000..029914f48 --- /dev/null +++ b/src/emqx_reason_codes.erl @@ -0,0 +1,110 @@ +%%%=================================================================== +%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%%% +%%% Licensed under the Apache License, Version 2.0 (the "License"); +%%% you may not use this file except in compliance with the License. +%%% You may obtain a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, software +%%% distributed under the License is distributed on an "AS IS" BASIS, +%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%%% See the License for the specific language governing permissions and +%%% limitations under the License. +%%%=================================================================== + +-module(emqx_reason_codes). + +-export([name/1, text/1]). + +name(16#00) -> success; +name(16#01) -> granted_qos1; +name(16#02) -> granted_qos2; +name(16#04) -> disconnect_with_will_message; +name(16#10) -> no_matching_subscribers; +name(16#11) -> no_subscription_existed; +name(16#18) -> continue_authentication; +name(16#19) -> re_authenticate; +name(16#80) -> unspecified_error; +name(16#81) -> malformed_Packet; +name(16#82) -> protocol_error; +name(16#83) -> implementation_specific_error; +name(16#84) -> unsupported_protocol_version; +name(16#85) -> client_identifier_not_valid; +name(16#86) -> bad_username_or_password; +name(16#87) -> not_authorized; +name(16#88) -> server_unavailable; +name(16#89) -> server_busy; +name(16#8A) -> banned; +name(16#8B) -> server_shutting_down; +name(16#8C) -> bad_authentication_method; +name(16#8D) -> keepalive_timeout; +name(16#8E) -> session_taken_over; +name(16#8F) -> topic_filter_invalid; +name(16#90) -> topic_name_invalid; +name(16#91) -> packet_identifier_inuse; +name(16#92) -> packet_identifier_not_found; +name(16#93) -> receive_maximum_exceeded; +name(16#94) -> topic_alias_invalid; +name(16#95) -> packet_too_large; +name(16#96) -> message_rate_too_high; +name(16#97) -> quota_exceeded; +name(16#98) -> administrative_action; +name(16#99) -> payload_format_invalid; +name(16#9A) -> retain_not_supported; +name(16#9B) -> qos_not_supported; +name(16#9C) -> use_another_server; +name(16#9D) -> server_moved; +name(16#9E) -> shared_subscriptions_not_supported; +name(16#9F) -> connection_rate_exceeded; +name(16#A0) -> maximum_connect_time; +name(16#A1) -> subscription_identifiers_not_supported; +name(16#A2) -> wildcard_subscriptions_not_supported; +name(Code) -> list_to_atom("unkown_" ++ integer_to_list(Code)). + +text(16#00) -> <<"Success">>; +text(16#01) -> <<"Granted QoS 1">>; +text(16#02) -> <<"Granted QoS 2">>; +text(16#04) -> <<"Disconnect with Will Message">>; +text(16#10) -> <<"No matching subscribers">>; +text(16#11) -> <<"No subscription existed">>; +text(16#18) -> <<"Continue authentication">>; +text(16#19) -> <<"Re-authenticate">>; +text(16#80) -> <<"Unspecified error">>; +text(16#81) -> <<"Malformed Packet">>; +text(16#82) -> <<"Protocol Error">>; +text(16#83) -> <<"Implementation specific error">>; +text(16#84) -> <<"Unsupported Protocol Version">>; +text(16#85) -> <<"Client Identifier not valid">>; +text(16#86) -> <<"Bad User Name or Password">>; +text(16#87) -> <<"Not authorized">>; +text(16#88) -> <<"Server unavailable">>; +text(16#89) -> <<"Server busy">>; +text(16#8A) -> <<"Banned">>; +text(16#8B) -> <<"Server shutting down">>; +text(16#8C) -> <<"Bad authentication method">>; +text(16#8D) -> <<"Keep Alive timeout">>; +text(16#8E) -> <<"Session taken over">>; +text(16#8F) -> <<"Topic Filter invalid">>; +text(16#90) -> <<"Topic Name invalid">>; +text(16#91) -> <<"Packet Identifier in use">>; +text(16#92) -> <<"Packet Identifier not found">>; +text(16#93) -> <<"Receive Maximum exceeded">>; +text(16#94) -> <<"Topic Alias invalid">>; +text(16#95) -> <<"Packet too large">>; +text(16#96) -> <<"Message rate too high">>; +text(16#97) -> <<"Quota exceeded">>; +text(16#98) -> <<"Administrative action">>; +text(16#99) -> <<"Payload format invalid">>; +text(16#9A) -> <<"Retain not supported">>; +text(16#9B) -> <<"QoS not supported">>; +text(16#9C) -> <<"Use another server">>; +text(16#9D) -> <<"Server moved">>; +text(16#9E) -> <<"Shared Subscriptions not supported">>; +text(16#9F) -> <<"Connection rate exceeded">>; +text(16#A0) -> <<"Maximum connect time">>; +text(16#A1) -> <<"Subscription Identifiers not supported">>; +text(16#A2) -> <<"Wildcard Subscriptions not supported">>; +text(Code) -> iolist_to_binary(["Unkown", integer_to_list(Code)]). + diff --git a/src/emqx_router.erl b/src/emqx_router.erl index dffc91133..c79482bd2 100644 --- a/src/emqx_router.erl +++ b/src/emqx_router.erl @@ -67,7 +67,7 @@ mnesia(copy) -> -spec(start_link(atom(), pos_integer()) -> {ok, pid()} | ignore | {error, term()}). start_link(Pool, Id) -> - gen_server:start_link(emqx_misc:proc_name(?MODULE, Id), + gen_server:start_link({local, emqx_misc:proc_name(?MODULE, Id)}, ?MODULE, [Pool, Id], [{hibernate_after, 10000}]). %%-------------------------------------------------------------------- diff --git a/src/emqx_serializer.erl b/src/emqx_serializer.erl index 0450a462f..670213674 100644 --- a/src/emqx_serializer.erl +++ b/src/emqx_serializer.erl @@ -1,18 +1,18 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. -%% -%% 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. -%%-------------------------------------------------------------------- +%%%=================================================================== +%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%%% +%%% Licensed under the Apache License, Version 2.0 (the "License"); +%%% you may not use this file except in compliance with the License. +%%% You may obtain a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, software +%%% distributed under the License is distributed on an "AS IS" BASIS, +%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%%% See the License for the specific language governing permissions and +%%% limitations under the License. +%%%=================================================================== -module(emqx_serializer). @@ -20,224 +20,266 @@ -include("emqx_mqtt.hrl"). -%% API --export([serialize/1]). +-type(option() :: {version, mqtt_version()}). -%% @doc Serialise MQTT Packet --spec(serialize(mqtt_packet()) -> iolist()). -serialize(#mqtt_packet{header = Header = #mqtt_packet_header{type = Type}, +-export_type([option/0]). + +-export([serialize/1, serialize/2]). + +-spec(serialize(mqtt_packet()) -> iodata()). +serialize(Packet) -> serialize(Packet, []). + +-spec(serialize(mqtt_packet(), [option()]) -> iodata()). +serialize(#mqtt_packet{header = Header, variable = Variable, - payload = Payload}) -> - serialize_header(Header, - serialize_variable(Type, Variable, - serialize_payload(Payload))). + payload = Payload}, Opts) when is_list(Opts) -> + Opts1 = parse_opt(Opts, #{version => ?MQTT_PROTO_V4}), + serialize(Header, serialize_variable(Variable, Opts1), serialize_payload(Payload)). -serialize_header(#mqtt_packet_header{type = Type, - dup = Dup, - qos = Qos, - retain = Retain}, - {VariableBin, PayloadBin}) - when ?CONNECT =< Type andalso Type =< ?DISCONNECT -> - Len = byte_size(VariableBin) + byte_size(PayloadBin), +parse_opt([], Map) -> + Map; +parse_opt([{version, Ver}|Opts], Map) -> + parse_opt(Opts, Map#{version := Ver}); +parse_opt([_|Opts], Map) -> + parse_opt(Opts, Map). + +serialize(#mqtt_packet_header{type = Type, + dup = Dup, + qos = Qos, + retain = Retain}, VariableData, PayloadData) + when ?CONNECT =< Type andalso Type =< ?AUTH -> + Len = iolist_size(VariableData) + iolist_size(PayloadData), true = (Len =< ?MAX_PACKET_SIZE), [<>, - serialize_len(Len), VariableBin, PayloadBin]. + serialize_remaining_len(Len), VariableData, PayloadData]. -serialize_variable(?CONNECT, #mqtt_packet_connect{client_id = ClientId, - proto_ver = ProtoVer, - proto_name = ProtoName, - will_retain = WillRetain, - will_qos = WillQos, - will_flag = WillFlag, - clean_sess = CleanSess, - keep_alive = KeepAlive, - will_topic = WillTopic, - will_msg = WillMsg, - username = Username, - password = Password}, undefined) -> - VariableBin = <<(byte_size(ProtoName)):16/big-unsigned-integer, - ProtoName/binary, - ProtoVer:8, - (opt(Username)):1, - (opt(Password)):1, - (opt(WillRetain)):1, - WillQos:2, - (opt(WillFlag)):1, - (opt(CleanSess)):1, - 0:1, - KeepAlive:16/big-unsigned-integer>>, - PayloadBin = serialize_utf(ClientId), - PayloadBin1 = case WillFlag of - true -> <>; - false -> PayloadBin - end, - UserPasswd = << <<(serialize_utf(B))/binary>> || B <- [Username, Password], B =/= undefined >>, - {VariableBin, <>}; +serialize_variable(#mqtt_packet_connect{proto_name = ProtoName, + proto_ver = ProtoVer, + is_bridge = IsBridge, + clean_start = CleanStart, + will_flag = WillFlag, + will_qos = WillQos, + will_retain = WillRetain, + keepalive = KeepAlive, + properties = Properties, + client_id = ClientId, + will_props = WillProps, + will_topic = WillTopic, + will_payload = WillPayload, + username = Username, + password = Password}, _Opts) -> + [serialize_binary_data(ProtoName), + <<(case IsBridge of + true -> 16#80 + ProtoVer; + false -> ProtoVer + end):8, + (opt(Username)):1, + (opt(Password)):1, + (opt(WillRetain)):1, + WillQos:2, + (opt(WillFlag)):1, + (opt(CleanStart)):1, + 0:1, + KeepAlive:16/big-unsigned-integer>>, + serialize_properties(Properties, ProtoVer), + serialize_utf8_string(ClientId), + case WillFlag of + true -> [serialize_properties(WillProps, ProtoVer), + serialize_utf8_string(WillTopic), + serialize_binary_data(WillPayload)]; + false -> <<>> + end, + serialize_utf8_string(Username, true), + serialize_utf8_string(Password, true)]; -serialize_variable(?CONNACK, #mqtt_packet_connack{ack_flags = AckFlags, - reason_code = ReasonCode, - properties = Properties}, undefined) -> - PropsBin = serialize_properties(Properties), - {<>, <<>>}; +serialize_variable(#mqtt_packet_connack{ack_flags = AckFlags, + reason_code = ReasonCode, + properties = Properties}, #{version := Ver}) -> + [AckFlags, ReasonCode, serialize_properties(Properties, Ver)]; -serialize_variable(?SUBSCRIBE, #mqtt_packet_subscribe{packet_id = PacketId, - topic_filters = TopicFilters}, undefined) -> - {<>, serialize_topics(TopicFilters)}; +serialize_variable(#mqtt_packet_publish{topic_name = TopicName, + packet_id = PacketId, + properties = Properties}, #{version := Ver}) -> + [serialize_utf8_string(TopicName), + if + PacketId =:= undefined -> <<>>; + true -> <> + end, + serialize_properties(Properties, Ver)]; -serialize_variable(?SUBACK, #mqtt_packet_suback{packet_id = PacketId, - properties = Properties, - reason_codes = ReasonCodes}, undefined) -> - io:format("SubAck ReasonCodes: ~p~n", [ReasonCodes]), - {<>, << <> || Code <- ReasonCodes >>}; +serialize_variable(#mqtt_packet_puback{packet_id = PacketId}, #{version := Ver}) + when Ver == ?MQTT_PROTO_V3; Ver == ?MQTT_PROTO_V4 -> + <>; +serialize_variable(#mqtt_packet_puback{packet_id = PacketId, + reason_code = ReasonCode, + properties = Properties}, + #{version := ?MQTT_PROTO_V5}) -> + [<>, ReasonCode, + serialize_properties(Properties, ?MQTT_PROTO_V5)]; -serialize_variable(?UNSUBSCRIBE, #mqtt_packet_unsubscribe{packet_id = PacketId, - topics = Topics }, undefined) -> - {<>, serialize_topics(Topics)}; +serialize_variable(#mqtt_packet_subscribe{packet_id = PacketId, + properties = Properties, + topic_filters = TopicFilters}, + #{version := Ver}) -> + [<>, serialize_properties(Properties, Ver), + serialize_topic_filters(subscribe, TopicFilters, Ver)]; -serialize_variable(?UNSUBACK, #mqtt_packet_unsuback{packet_id = PacketId, - properties = Properties, - reason_codes = ReasonCodes}, undefined) -> - {<>, << <> || Code <- ReasonCodes >>}; +serialize_variable(#mqtt_packet_suback{packet_id = PacketId, + properties = Properties, + reason_codes = ReasonCodes}, + #{version := Ver}) -> + [<>, serialize_properties(Properties, Ver), + << <> || Code <- ReasonCodes >>]; -serialize_variable(?PUBLISH, #mqtt_packet_publish{topic_name = TopicName, - packet_id = PacketId }, PayloadBin) -> - TopicBin = serialize_utf(TopicName), - PacketIdBin = if - PacketId =:= undefined -> <<>>; - true -> <> - end, - {<>, PayloadBin}; +serialize_variable(#mqtt_packet_unsubscribe{packet_id = PacketId, + properties = Properties, + topic_filters = TopicFilters}, + #{version := Ver}) -> + [<>, serialize_properties(Properties, Ver), + serialize_topic_filters(unsubscribe, TopicFilters, Ver)]; -serialize_variable(PubAck, #mqtt_packet_puback{packet_id = PacketId}, _Payload) - when PubAck =:= ?PUBACK; PubAck =:= ?PUBREC; PubAck =:= ?PUBREL; PubAck =:= ?PUBCOMP -> - {<>, <<>>}; +serialize_variable(#mqtt_packet_unsuback{packet_id = PacketId, + properties = Properties, + reason_codes = ReasonCodes}, + #{version := Ver}) -> + [<>, serialize_properties(Properties, Ver), + << <> || Code <- ReasonCodes >>]; -serialize_variable(?PINGREQ, undefined, undefined) -> - {<<>>, <<>>}; +serialize_variable(#mqtt_packet_disconnect{}, #{version := Ver}) + when Ver == ?MQTT_PROTO_V3; Ver == ?MQTT_PROTO_V4 -> + <<>>; -serialize_variable(?PINGRESP, undefined, undefined) -> - {<<>>, <<>>}; +serialize_variable(#mqtt_packet_disconnect{reason_code = ReasonCode, + properties = Properties}, + #{version := Ver = ?MQTT_PROTO_V5}) -> + [ReasonCode, serialize_properties(Properties, Ver)]; +serialize_variable(#mqtt_packet_disconnect{}, _Ver) -> + <<>>; -serialize_variable(?DISCONNECT, #mqtt_packet_disconnect{reason_code = ReasonCode, - properties = Properties}, undefined) -> - {<>, <<>>}; +serialize_variable(#mqtt_packet_auth{reason_code = ReasonCode, + properties = Properties}, + #{version := Ver = ?MQTT_PROTO_V5}) -> + [ReasonCode, serialize_properties(Properties, Ver)]; -serialize_variable(?AUTH, #mqtt_packet_auth{reason_code = ReasonCode, - properties = Properties}, undefined) -> - {<>, <<>>}. +serialize_variable(PacketId, ?MQTT_PROTO_V3) when is_integer(PacketId) -> + <>; +serialize_variable(PacketId, ?MQTT_PROTO_V4) when is_integer(PacketId) -> + <>; +serialize_variable(undefined, _Ver) -> + <<>>. serialize_payload(undefined) -> - undefined; -serialize_payload(Bin) when is_binary(Bin) -> + <<>>; +serialize_payload(Bin) when is_binary(Bin); is_list(Bin) -> Bin. -serialize_properties(undefined) -> +serialize_properties(_Props, Ver) when Ver =/= ?MQTT_PROTO_V5 -> <<>>; -serialize_properties(Props) -> - << <<(serialize_property(Prop, Val))/binary>> || {Prop, Val} <- maps:to_list(Props) >>. +serialize_properties(Props, ?MQTT_PROTO_V5) -> + serialize_properties(Props). -%% 01: Byte; +serialize_properties(undefined) -> + <<0>>; +serialize_properties(Props) when map_size(Props) == 0 -> + <<0>>; +serialize_properties(Props) when is_map(Props) -> + Bin = << <<(serialize_property(Prop, Val))/binary>> || {Prop, Val} <- maps:to_list(Props) >>, + [serialize_variable_byte_integer(byte_size(Bin)), Bin]. + +%% Ignore undefined +serialize_property(_, undefined) -> + <<>>; serialize_property('Payload-Format-Indicator', Val) -> <<16#01, Val>>; -%% 02: Four Byte Integer; serialize_property('Message-Expiry-Interval', Val) -> <<16#02, Val:32/big>>; -%% 03: UTF-8 Encoded String; serialize_property('Content-Type', Val) -> - <<16#03, (serialize_utf(Val))/binary>>; -%% 08: UTF-8 Encoded String; + <<16#03, (serialize_utf8_string(Val))/binary>>; serialize_property('Response-Topic', Val) -> - <<16#08, (serialize_utf(Val))/binary>>; -%% 09: Binary Data; + <<16#08, (serialize_utf8_string(Val))/binary>>; serialize_property('Correlation-Data', Val) -> - <<16#09, (iolist_size(Val)):16, Val/binary>>; -%% 11: Variable Byte Integer; + <<16#09, (byte_size(Val)):16, Val/binary>>; serialize_property('Subscription-Identifier', Val) -> <<16#0B, (serialize_variable_byte_integer(Val))/binary>>; -%% 17: Four Byte Integer; serialize_property('Session-Expiry-Interval', Val) -> <<16#11, Val:32/big>>; -%% 18: UTF-8 Encoded String; serialize_property('Assigned-Client-Identifier', Val) -> - <<16#12, (serialize_utf(Val))/binary>>; -%% 19: Two Byte Integer; + <<16#12, (serialize_utf8_string(Val))/binary>>; serialize_property('Server-Keep-Alive', Val) -> <<16#13, Val:16/big>>; -%% 21: UTF-8 Encoded String; serialize_property('Authentication-Method', Val) -> - <<16#15, (serialize_utf(Val))/binary>>; -%% 22: Binary Data; + <<16#15, (serialize_utf8_string(Val))/binary>>; serialize_property('Authentication-Data', Val) -> <<16#16, (iolist_size(Val)):16, Val/binary>>; -%% 23: Byte; serialize_property('Request-Problem-Information', Val) -> <<16#17, Val>>; -%% 24: Four Byte Integer; serialize_property('Will-Delay-Interval', Val) -> <<16#18, Val:32/big>>; -%% 25: Byte; serialize_property('Request-Response-Information', Val) -> <<16#19, Val>>; -%% 26: UTF-8 Encoded String; serialize_property('Response-Information', Val) -> - <<16#1A, (serialize_utf(Val))/binary>>; -%% 28: UTF-8 Encoded String; + <<16#1A, (serialize_utf8_string(Val))/binary>>; serialize_property('Server-Reference', Val) -> - <<16#1C, (serialize_utf(Val))/binary>>; -%% 31: UTF-8 Encoded String; + <<16#1C, (serialize_utf8_string(Val))/binary>>; serialize_property('Reason-String', Val) -> - <<16#1F, (serialize_utf(Val))/binary>>; -%% 33: Two Byte Integer; + <<16#1F, (serialize_utf8_string(Val))/binary>>; serialize_property('Receive-Maximum', Val) -> <<16#21, Val:16/big>>; -%% 34: Two Byte Integer; serialize_property('Topic-Alias-Maximum', Val) -> <<16#22, Val:16/big>>; -%% 35: Two Byte Integer; serialize_property('Topic-Alias', Val) -> <<16#23, Val:16/big>>; -%% 36: Byte; serialize_property('Maximum-QoS', Val) -> <<16#24, Val>>; -%% 37: Byte; serialize_property('Retain-Available', Val) -> <<16#25, Val>>; -%% 38: UTF-8 String Pair; -serialize_property('User-Property', Val) -> - <<16#26, (serialize_utf_pair(Val))/binary>>; -%% 39: Four Byte Integer; +serialize_property('User-Property', {Key, Val}) -> + <<16#26, (serialize_utf8_pair({Key, Val}))/binary>>; +serialize_property('User-Property', Props) when is_list(Props) -> + << <<(serialize_property('User-Property', {Key, Val}))/binary>> + || {Key, Val} <- Props >>; serialize_property('Maximum-Packet-Size', Val) -> <<16#27, Val:32/big>>; -%% 40: Byte; serialize_property('Wildcard-Subscription-Available', Val) -> <<16#28, Val>>; -%% 41: Byte; serialize_property('Subscription-Identifier-Available', Val) -> <<16#29, Val>>; -%% 42: Byte; serialize_property('Shared-Subscription-Available', Val) -> <<16#2A, Val>>. -serialize_topics([{_Topic, _Qos}|_] = Topics) -> - << <<(serialize_utf(Topic))/binary, ?RESERVED:6, Qos:2>> || {Topic, Qos} <- Topics >>; +serialize_topic_filters(subscribe, TopicFilters, ?MQTT_PROTO_V5) -> + << <<(serialize_utf8_string(Topic))/binary, ?RESERVED:2, Rh:2, (opt(Rap)):1, (opt(Nl)):1, Qos:2>> + || {Topic, #mqtt_subopts{rh = Rh, rap = Rap, nl = Nl, qos = Qos}} <- TopicFilters >>; -serialize_topics([H|_] = Topics) when is_binary(H) -> - << <<(serialize_utf(Topic))/binary>> || Topic <- Topics >>. +serialize_topic_filters(subscribe, TopicFilters, _Ver) -> + << <<(serialize_utf8_string(Topic))/binary, ?RESERVED:6, Qos:2>> + || {Topic, #mqtt_subopts{qos = Qos}} <- TopicFilters >>; -serialize_utf_pair({Name, Value}) -> - << <<(serialize_utf(S))/binary, (serialize_utf(S))/binary>> || S <- [Name, Value] >>. +serialize_topic_filters(unsubscribe, TopicFilters, _Ver) -> + << <<(serialize_utf8_string(Topic))/binary>> || Topic <- TopicFilters >>. -serialize_utf(String) -> +serialize_utf8_pair({Name, Value}) -> + << <<(serialize_utf8_string(S))/binary, + (serialize_utf8_string(S))/binary>> || S <- [Name, Value] >>. + +serialize_binary_data(Bin) -> + [<<(byte_size(Bin)):16/big-unsigned-integer>>, Bin]. + +serialize_utf8_string(undefined, false) -> + error(utf8_string_undefined); +serialize_utf8_string(undefined, true) -> + <<>>; +serialize_utf8_string(String, _AllowNull) -> + serialize_utf8_string(String). + +serialize_utf8_string(String) -> StringBin = unicode:characters_to_binary(String), Len = byte_size(StringBin), true = (Len =< 16#ffff), <>. -serialize_len(I) -> - serialize_variable_byte_integer(I). %%TODO: refactor later. +serialize_remaining_len(I) -> + serialize_variable_byte_integer(I). serialize_variable_byte_integer(N) when N =< ?LOWBITS -> <<0:1, N:7>>; diff --git a/src/emqx_session.erl b/src/emqx_session.erl index 3d2716099..1dbe1e83a 100644 --- a/src/emqx_session.erl +++ b/src/emqx_session.erl @@ -725,10 +725,10 @@ acked(puback, PacketId, State = #state{client_id = ClientId, username = Username, inflight = Inflight}) -> case Inflight:lookup(PacketId) of - {publish, Msg, _Ts} -> + {value, {publish, Msg, _Ts}} -> emqx_hooks:run('message.acked', [ClientId, Username], Msg), State#state{inflight = Inflight:delete(PacketId)}; - _ -> + none -> ?LOG(warning, "Duplicated PUBACK Packet: ~p", [PacketId], State), State end; @@ -737,11 +737,14 @@ acked(pubrec, PacketId, State = #state{client_id = ClientId, username = Username, inflight = Inflight}) -> case Inflight:lookup(PacketId) of - {publish, Msg, _Ts} -> + {value, {publish, Msg, _Ts}} -> emqx_hooks:run('message.acked', [ClientId, Username], Msg), State#state{inflight = Inflight:update(PacketId, {pubrel, PacketId, os:timestamp()})}; - {pubrel, PacketId, _Ts} -> + {value, {pubrel, PacketId, _Ts}} -> ?LOG(warning, "Duplicated PUBREC Packet: ~p", [PacketId], State), + State; + none -> + ?LOG(warning, "Unexpected PUBREC Packet: ~p", [PacketId], State), State end; diff --git a/src/emqx_sm_sup.erl b/src/emqx_sm_sup.erl index 16e1b8715..b01f13e41 100644 --- a/src/emqx_sm_sup.erl +++ b/src/emqx_sm_sup.erl @@ -38,5 +38,5 @@ init([]) -> Manager = {manager, {emqx_sm, start_link, []}, permanent, 5000, worker, [emqx_sm]}, - {ok, {{one_for_rest, 10, 3600}, [Locker, Registry, Manager]}}. + {ok, {{rest_for_one, 10, 3600}, [Locker, Registry, Manager]}}. diff --git a/test/emqx_access_SUITE.erl b/test/emqx_access_SUITE.erl index ac79daa3c..aee73b873 100644 --- a/test/emqx_access_SUITE.erl +++ b/test/emqx_access_SUITE.erl @@ -118,8 +118,8 @@ unregister_mod(_) -> [] = ?AC:lookup_mods(auth). check_acl(_) -> - User1 = #mqtt_client{client_id = <<"client1">>, username = <<"testuser">>}, - User2 = #mqtt_client{client_id = <<"client2">>, username = <<"xyz">>}, + User1 = #client{client_id = <<"client1">>, username = <<"testuser">>}, + User2 = #client{client_id = <<"client2">>, username = <<"xyz">>}, allow = ?AC:check_acl(User1, subscribe, <<"users/testuser/1">>), allow = ?AC:check_acl(User1, subscribe, <<"clients/client1">>), allow = ?AC:check_acl(User1, subscribe, <<"clients/client1/x/y">>), @@ -158,8 +158,8 @@ compile_rule(_) -> {deny, all} = compile({deny, all}). match_rule(_) -> - User = #mqtt_client{peername = {{127,0,0,1}, 2948}, client_id = <<"testClient">>, username = <<"TestUser">>}, - User2 = #mqtt_client{peername = {{192,168,0,10}, 3028}, client_id = <<"testClient">>, username = <<"TestUser">>}, + User = #client{peername = {{127,0,0,1}, 2948}, client_id = <<"testClient">>, username = <<"TestUser">>}, + User2 = #client{peername = {{192,168,0,10}, 3028}, client_id = <<"testClient">>, username = <<"TestUser">>}, {matched, allow} = match(User, <<"Test/Topic">>, {allow, all}), {matched, deny} = match(User, <<"Test/Topic">>, {deny, all}), @@ -169,7 +169,7 @@ match_rule(_) -> nomatch = match(User, <<"d/e/f/x">>, compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]})), {matched, allow} = match(User, <<"testTopics/testClient">>, compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]})), {matched, allow} = match(User, <<"clients/testClient">>, compile({allow, all, pubsub, ["clients/%c"]})), - {matched, allow} = match(#mqtt_client{username = <<"user2">>}, <<"users/user2/abc/def">>, + {matched, allow} = match(#client{username = <<"user2">>}, <<"users/user2/abc/def">>, compile({allow, all, subscribe, ["users/%u/#"]})), {matched, deny} = match(User, <<"d/e/f">>, compile({deny, all, subscribe, ["$SYS/#", "#"]})), Rule = compile({allow, {'and', [{ipaddr, "127.0.0.1"}, {user, <<"WrongUser">>}]}, publish, <<"Topic">>}), diff --git a/test/emqx_protocol_SUITE.erl b/test/emqx_protocol_SUITE.erl index fac287f74..0d86beea0 100644 --- a/test/emqx_protocol_SUITE.erl +++ b/test/emqx_protocol_SUITE.erl @@ -87,7 +87,7 @@ parse_connect(_) -> keep_alive = 60}}, <<>>} = emqx_parser:parse(V31ConnBin, Parser), %% CONNECT(Q0, R0, D0, ClientId=mosqpub/10451-iMac.loca, ProtoName=MQTT, ProtoVsn=4, CleanSess=true, KeepAlive=60, Username=undefined, Password=undefined) V311ConnBin = <<16,35,0,4,77,81,84,84,4,2,0,60,0,23,109,111,115,113,112,117,98,47,49,48,52,53,49,45,105,77,97,99,46,108,111,99,97>>, - {ok, #mqtt_packet{header = #mqtt_packet_header{type = ?CONNECT, + {ok, #mqtt_packet{header = #mqtt_packet_header{type = ?CONNECT, dup = false, qos = 0, retain = false}, @@ -160,7 +160,7 @@ parse_publish(_) -> variable = #mqtt_packet_publish{topic_name = <<"a/b/c">>, packet_id = 1}, payload = <<"hahah">> }, <<>>} = emqx_parser:parse(PubBin, Parser), - + %PUBLISH(Qos=0, Retain=false, Dup=false, TopicName=xxx/yyy, PacketId=undefined, Payload=<<"hello">>) %DISCONNECT(Qos=0, Retain=false, Dup=false) PubBin1 = <<48,14,0,7,120,120,120,47,121,121,121,104,101,108,108,111,224,0>>, @@ -244,62 +244,6 @@ parse_disconnect(_) -> qos = 0, retain = false}}, <<>>} = emqx_parser:parse(Bin, Parser). -%%-------------------------------------------------------------------- -%% Serialize Cases -%%-------------------------------------------------------------------- - -serialize_connect(_) -> - serialize(?CONNECT_PACKET(#mqtt_packet_connect{})), - serialize(?CONNECT_PACKET(#mqtt_packet_connect{ - client_id = <<"clientId">>, - will_qos = ?QOS1, - will_flag = true, - will_retain = true, - will_topic = <<"will">>, - will_msg = <<"haha">>, - clean_sess = true})). - -serialize_connack(_) -> - ConnAck = #mqtt_packet{header = #mqtt_packet_header{type = ?CONNACK}, - variable = #mqtt_packet_connack{ack_flags = 0, return_code = 0}}, - ?assertEqual(<<32,2,0,0>>, iolist_to_binary(serialize(ConnAck))). - -serialize_publish(_) -> - serialize(?PUBLISH_PACKET(?QOS_0, <<"Topic">>, undefined, <<"Payload">>)), - serialize(?PUBLISH_PACKET(?QOS_1, <<"Topic">>, 938, <<"Payload">>)), - serialize(?PUBLISH_PACKET(?QOS_2, <<"Topic">>, 99, long_payload())). - -serialize_puback(_) -> - serialize(?PUBACK_PACKET(?PUBACK, 10384)). - -serialize_pubrel(_) -> - serialize(?PUBREL_PACKET(10384)). - -serialize_subscribe(_) -> - TopicTable = [{<<"TopicQos0">>, ?QOS_0}, {<<"TopicQos1">>, ?QOS_1}, {<<"TopicQos2">>, ?QOS_2}], - serialize(?SUBSCRIBE_PACKET(10, TopicTable)). - -serialize_suback(_) -> - serialize(?SUBACK_PACKET(10, [?QOS_0, ?QOS_1, 128])). - -serialize_unsubscribe(_) -> - serialize(?UNSUBSCRIBE_PACKET(10, [<<"Topic1">>, <<"Topic2">>])). - -serialize_unsuback(_) -> - serialize(?UNSUBACK_PACKET(10)). - -serialize_pingreq(_) -> - serialize(?PACKET(?PINGREQ)). - -serialize_pingresp(_) -> - serialize(?PACKET(?PINGRESP)). - -serialize_disconnect(_) -> - serialize(?PACKET(?DISCONNECT)). - -long_payload() -> - iolist_to_binary(["payload." || _I <- lists:seq(1, 100)]). - %%-------------------------------------------------------------------- %% Packet Cases %%-------------------------------------------------------------------- diff --git a/test/emqx_serializer_SUITE.erl b/test/emqx_serializer_SUITE.erl new file mode 100644 index 000000000..d0a34fd20 --- /dev/null +++ b/test/emqx_serializer_SUITE.erl @@ -0,0 +1,91 @@ +%%%=================================================================== +%%% Copyright (c) 2013-2018 EMQ Inc. All rights reserved. +%%% +%%% Licensed under the Apache License, Version 2.0 (the "License"); +%%% you may not use this file except in compliance with the License. +%%% You may obtain a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, software +%%% distributed under the License is distributed on an "AS IS" BASIS, +%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%%% See the License for the specific language governing permissions and +%%% limitations under the License. +%%%=================================================================== + +-module(emqx_serializer_SUITE). + +-compile(export_all). + +-include("emqx_mqtt.hrl"). + +-include_lib("eunit/include/eunit.hrl"). + +-import(emqx_serializer, [serialize/1]). + +all() -> + [serialize_connect, + serialize_connack, + serialize_publish, + serialize_puback, + serialize_pubrel, + serialize_subscribe, + serialize_suback, + serialize_unsubscribe, + serialize_unsuback, + serialize_pingreq, + serialize_pingresp, + serialize_disconnect]. + +serialize_connect(_) -> + serialize(?CONNECT_PACKET(#mqtt_packet_connect{})), + serialize(?CONNECT_PACKET(#mqtt_packet_connect{ + client_id = <<"clientId">>, + will_qos = ?QOS1, + will_flag = true, + will_retain = true, + will_topic = <<"will">>, + will_payload = <<"haha">>, + clean_sess = true})). + +serialize_connack(_) -> + ConnAck = #mqtt_packet{header = #mqtt_packet_header{type = ?CONNACK}, + variable = #mqtt_packet_connack{ack_flags = 0, return_code = 0}}, + ?assertEqual(<<32,2,0,0>>, iolist_to_binary(serialize(ConnAck))). + +serialize_publish(_) -> + serialize(?PUBLISH_PACKET(?QOS_0, <<"Topic">>, undefined, <<"Payload">>)), + serialize(?PUBLISH_PACKET(?QOS_1, <<"Topic">>, 938, <<"Payload">>)), + serialize(?PUBLISH_PACKET(?QOS_2, <<"Topic">>, 99, long_payload())). + +serialize_puback(_) -> + serialize(?PUBACK_PACKET(?PUBACK, 10384)). + +serialize_pubrel(_) -> + serialize(?PUBREL_PACKET(10384)). + +serialize_subscribe(_) -> + TopicTable = [{<<"TopicQos0">>, ?QOS_0}, {<<"TopicQos1">>, ?QOS_1}, {<<"TopicQos2">>, ?QOS_2}], + serialize(?SUBSCRIBE_PACKET(10, TopicTable)). + +serialize_suback(_) -> + serialize(?SUBACK_PACKET(10, [?QOS_0, ?QOS_1, 128])). + +serialize_unsubscribe(_) -> + serialize(?UNSUBSCRIBE_PACKET(10, [<<"Topic1">>, <<"Topic2">>])). + +serialize_unsuback(_) -> + serialize(?UNSUBACK_PACKET(10)). + +serialize_pingreq(_) -> + serialize(?PACKET(?PINGREQ)). + +serialize_pingresp(_) -> + serialize(?PACKET(?PINGRESP)). + +serialize_disconnect(_) -> + serialize(?PACKET(?DISCONNECT)). + +long_payload() -> + iolist_to_binary(["payload." || _I <- lists:seq(1, 100)]).