diff --git a/apps/emqx_gateway/src/emqx_gateway.app.src b/apps/emqx_gateway/src/emqx_gateway.app.src index bfcf4f2f2..6db4b0674 100644 --- a/apps/emqx_gateway/src/emqx_gateway.app.src +++ b/apps/emqx_gateway/src/emqx_gateway.app.src @@ -1,7 +1,7 @@ %% -*- mode: erlang -*- {application, emqx_gateway, [ {description, "The Gateway management application"}, - {vsn, "0.1.20"}, + {vsn, "0.1.21"}, {registered, []}, {mod, {emqx_gateway_app, []}}, {applications, [kernel, stdlib, emqx, emqx_authn, emqx_ctl]}, diff --git a/apps/emqx_gateway/src/emqx_gateway_utils.erl b/apps/emqx_gateway/src/emqx_gateway_utils.erl index 634a02f03..eb4ce9fdf 100644 --- a/apps/emqx_gateway/src/emqx_gateway_utils.erl +++ b/apps/emqx_gateway/src/emqx_gateway_utils.erl @@ -46,7 +46,8 @@ global_chain/1, listener_chain/3, find_gateway_definitions/0, - plus_max_connections/2 + plus_max_connections/2, + random_clientid/1 ]). -export([stringfy/1]). @@ -631,3 +632,6 @@ ensure_gateway_loaded() -> emqx_gateway_mqttsn ] ). + +random_clientid(GwName) when is_atom(GwName) -> + iolist_to_binary([atom_to_list(GwName), "-", emqx_utils:gen_id()]). diff --git a/apps/emqx_gateway_coap/src/emqx_coap_channel.erl b/apps/emqx_gateway_coap/src/emqx_coap_channel.erl index 21066655e..d95dc5bd2 100644 --- a/apps/emqx_gateway_coap/src/emqx_coap_channel.erl +++ b/apps/emqx_gateway_coap/src/emqx_coap_channel.erl @@ -118,8 +118,8 @@ info(ctx, #channel{ctx = Ctx}) -> Ctx. -spec stats(channel()) -> emqx_types:stats(). -stats(_) -> - []. +stats(#channel{session = Session}) -> + emqx_coap_session:stats(Session). -spec init(map(), map()) -> channel(). init( @@ -273,7 +273,7 @@ handle_call( SubReq, TempMsg, #{}, Session ), NSession = maps:get(session, Result), - {reply, {ok, {MountedTopic, NSubOpts}}, Channel#channel{session = NSession}}; + {reply, {ok, {MountedTopic, NSubOpts}}, [{event, updated}], Channel#channel{session = NSession}}; handle_call( {unsubscribe, Topic}, _From, @@ -300,7 +300,7 @@ handle_call( UnSubReq, TempMsg, #{}, Session ), NSession = maps:get(session, Result), - {reply, ok, Channel#channel{session = NSession}}; + {reply, ok, [{event, updated}], Channel#channel{session = NSession}}; handle_call(subscriptions, _From, Channel = #channel{session = Session}) -> Subs = emqx_coap_session:info(subscriptions, Session), {reply, {ok, maps:to_list(Subs)}, Channel}; @@ -486,7 +486,6 @@ enrich_conninfo( conninfo = ConnInfo } ) -> - %% FIXME: generate a random clientid if absent case Queries of #{<<"clientid">> := ClientId} -> Interval = maps:get(interval, emqx_keepalive:info(KeepAlive)), @@ -500,32 +499,20 @@ enrich_conninfo( }, {ok, Channel#channel{conninfo = NConnInfo}}; _ -> - {error, "invalid queries", Channel} + {error, "clientid is required", Channel} end. enrich_clientinfo( {Queries, Msg}, - Channel = #channel{clientinfo = ClientInfo0} + Channel = #channel{conninfo = ConnInfo, clientinfo = ClientInfo0} ) -> - %% FIXME: - %% 1. generate a random clientid if absent; - %% 2. assgin username, password to `undefined` if absent - case Queries of - #{ - <<"username">> := UserName, - <<"password">> := Password, - <<"clientid">> := ClientId - } -> - ClientInfo = ClientInfo0#{ - username => UserName, - password => Password, - clientid => ClientId - }, - {ok, NClientInfo} = fix_mountpoint(Msg, ClientInfo), - {ok, Channel#channel{clientinfo = NClientInfo}}; - _ -> - {error, "invalid queries", Channel} - end. + ClientInfo = ClientInfo0#{ + clientid => maps:get(clientid, ConnInfo), + username => maps:get(<<"username">>, Queries, undefined), + password => maps:get(<<"password">>, Queries, undefined) + }, + {ok, NClientInfo} = fix_mountpoint(Msg, ClientInfo), + {ok, Channel#channel{clientinfo = NClientInfo}}. set_log_meta(_Input, #channel{clientinfo = #{clientid := ClientId}}) -> emqx_logger:set_metadata_clientid(ClientId), diff --git a/apps/emqx_gateway_coap/src/emqx_coap_session.erl b/apps/emqx_gateway_coap/src/emqx_coap_session.erl index 5ae169675..562369e2f 100644 --- a/apps/emqx_gateway_coap/src/emqx_coap_session.erl +++ b/apps/emqx_gateway_coap/src/emqx_coap_session.erl @@ -117,15 +117,15 @@ info(inflight, _) -> info(inflight_cnt, _) -> 0; info(inflight_max, _) -> - 0; + infinity; info(retry_interval, _) -> infinity; info(mqueue, _) -> emqx_mqueue:init(#{max_len => 0, store_qos0 => false}); -info(mqueue_len, #session{transport_manager = TM}) -> - maps:size(TM); -info(mqueue_max, _) -> +info(mqueue_len, _) -> 0; +info(mqueue_max, _) -> + infinity; info(mqueue_dropped, _) -> 0; info(next_pkt_id, _) -> diff --git a/apps/emqx_gateway_coap/src/emqx_gateway_coap.app.src b/apps/emqx_gateway_coap/src/emqx_gateway_coap.app.src index e03066695..a0cbc3e18 100644 --- a/apps/emqx_gateway_coap/src/emqx_gateway_coap.app.src +++ b/apps/emqx_gateway_coap/src/emqx_gateway_coap.app.src @@ -1,6 +1,6 @@ {application, emqx_gateway_coap, [ {description, "CoAP Gateway"}, - {vsn, "0.1.1"}, + {vsn, "0.1.2"}, {registered, []}, {applications, [kernel, stdlib, emqx, emqx_gateway]}, {env, []}, diff --git a/apps/emqx_gateway_coap/test/emqx_coap_SUITE.erl b/apps/emqx_gateway_coap/test/emqx_coap_SUITE.erl index 999493a79..ce809184e 100644 --- a/apps/emqx_gateway_coap/test/emqx_coap_SUITE.erl +++ b/apps/emqx_gateway_coap/test/emqx_coap_SUITE.erl @@ -133,6 +133,42 @@ t_connection(_) -> end, do(Action). +t_connection_optional_params(_) -> + UsernamePasswordAreOptional = + fun(Channel) -> + URI = + ?MQTT_PREFIX ++ + "/connection?clientid=client1", + Req = make_req(post), + {ok, created, Data} = do_request(Channel, URI, Req), + #coap_content{payload = Token0} = Data, + Token = binary_to_list(Token0), + + timer:sleep(100), + ?assertNotEqual( + [], + emqx_gateway_cm_registry:lookup_channels(coap, <<"client1">>) + ), + + disconnection(Channel, Token), + + timer:sleep(100), + ?assertEqual( + [], + emqx_gateway_cm_registry:lookup_channels(coap, <<"client1">>) + ) + end, + ClientIdIsRequired = + fun(Channel) -> + URI = + ?MQTT_PREFIX ++ + "/connection", + Req = make_req(post), + {error, bad_request, _} = do_request(Channel, URI, Req) + end, + do(UsernamePasswordAreOptional), + do(ClientIdIsRequired). + t_connection_with_authn_failed(_) -> ChId = {{127, 0, 0, 1}, 5683}, {ok, Sock} = er_coap_udp_socket:start_link(), @@ -327,6 +363,9 @@ t_clients_subscription_api(_) -> maps:get(topic, SubsResp2) ), + %% check subscription_cnt + {200, #{subscriptions_cnt := 1}} = request(get, "/gateways/coap/clients/client1"), + {204, _} = request(delete, Path ++ "/tx"), {200, []} = request(get, Path) diff --git a/apps/emqx_gateway_exproto/src/emqx_exproto_channel.erl b/apps/emqx_gateway_exproto/src/emqx_exproto_channel.erl index 2a144ffeb..5de597920 100644 --- a/apps/emqx_gateway_exproto/src/emqx_exproto_channel.erl +++ b/apps/emqx_gateway_exproto/src/emqx_exproto_channel.erl @@ -782,7 +782,7 @@ enrich_clientinfo(InClientInfo = #{proto_name := ProtoName}, ClientInfo) -> default_conninfo(ConnInfo) -> ConnInfo#{ clean_start => true, - clientid => anonymous_clientid(), + clientid => emqx_gateway_utils:random_clientid(exproto), username => undefined, conn_props => #{}, connected => true, @@ -822,6 +822,3 @@ proto_name_to_protocol(<<>>) -> exproto; proto_name_to_protocol(ProtoName) when is_binary(ProtoName) -> binary_to_atom(ProtoName). - -anonymous_clientid() -> - iolist_to_binary(["exproto-", emqx_utils:gen_id()]). diff --git a/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src b/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src index 66f9ddc89..5959eea3d 100644 --- a/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src +++ b/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src @@ -1,6 +1,6 @@ {application, emqx_gateway_exproto, [ {description, "ExProto Gateway"}, - {vsn, "0.1.2"}, + {vsn, "0.1.3"}, {registered, []}, {applications, [kernel, stdlib, grpc, emqx, emqx_gateway]}, {env, []}, diff --git a/changes/ce/fix-11206.en.md b/changes/ce/fix-11206.en.md new file mode 100644 index 000000000..e16b1e3f8 --- /dev/null +++ b/changes/ce/fix-11206.en.md @@ -0,0 +1 @@ +Make the username and password params of CoAP client to optional in connection mode.