fix(lwm2m): better logging for unknown object IDs
Prior to this change, unknown object IDs would result in a tuple {error, no_xml_definition}, and this tuple is passed down to xmerl lib to get XML node data and eventually crash with function_clause. With this fix, the unknown object ID exception is caught and logged properly.
This commit is contained in:
parent
699489297b
commit
13f5c0b6b1
|
@ -9,6 +9,7 @@
|
||||||
* The license is now copied to all nodes in the cluster when it's reloaded. [#8598](https://github.com/emqx/emqx/pull/8598)
|
* The license is now copied to all nodes in the cluster when it's reloaded. [#8598](https://github.com/emqx/emqx/pull/8598)
|
||||||
* Added a HTTP API to manage licenses. [#8610](https://github.com/emqx/emqx/pull/8610)
|
* Added a HTTP API to manage licenses. [#8610](https://github.com/emqx/emqx/pull/8610)
|
||||||
* Updated `/nodes` API node_status from `Running/Stopped` to `running/stopped`. [#8642](https://github.com/emqx/emqx/pull/8642)
|
* Updated `/nodes` API node_status from `Running/Stopped` to `running/stopped`. [#8642](https://github.com/emqx/emqx/pull/8642)
|
||||||
|
* Better logging on unknown object IDs. [#8670](https://github.com/emqx/emqx/pull/8670)
|
||||||
|
|
||||||
# 5.0.4
|
# 5.0.4
|
||||||
|
|
||||||
|
|
|
@ -221,14 +221,16 @@ read_resp_to_mqtt({ok, SuccessCode}, CoapPayload, Format, Ref) ->
|
||||||
Result = content_to_mqtt(CoapPayload, Format, Ref),
|
Result = content_to_mqtt(CoapPayload, Format, Ref),
|
||||||
make_response(SuccessCode, Ref, Format, Result)
|
make_response(SuccessCode, Ref, Format, Result)
|
||||||
catch
|
catch
|
||||||
error:not_implemented ->
|
throw:{bad_request, Reason} ->
|
||||||
make_response(not_implemented, Ref);
|
?SLOG(error, #{msg => "bad_request", payload => CoapPayload, reason => Reason}),
|
||||||
_:Ex:_ST ->
|
make_response(bad_request, Ref);
|
||||||
|
E:R:ST ->
|
||||||
?SLOG(error, #{
|
?SLOG(error, #{
|
||||||
msg => "bad_payload_format",
|
msg => "bad_request",
|
||||||
payload => CoapPayload,
|
payload => CoapPayload,
|
||||||
reason => Ex,
|
exception => E,
|
||||||
stacktrace => _ST
|
reason => R,
|
||||||
|
stacktrace => ST
|
||||||
}),
|
}),
|
||||||
make_response(bad_request, Ref)
|
make_response(bad_request, Ref)
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
tlv_to_json(BaseName, TlvData) ->
|
tlv_to_json(BaseName, TlvData) ->
|
||||||
DecodedTlv = emqx_lwm2m_tlv:parse(TlvData),
|
DecodedTlv = emqx_lwm2m_tlv:parse(TlvData),
|
||||||
ObjectId = object_id(BaseName),
|
ObjectId = object_id(BaseName),
|
||||||
ObjDefinition = emqx_lwm2m_xml_object:get_obj_def(ObjectId, true),
|
ObjDefinition = emqx_lwm2m_xml_object:get_obj_def_assertive(ObjectId, true),
|
||||||
case DecodedTlv of
|
case DecodedTlv of
|
||||||
[#{tlv_resource_with_value := Id, value := Value}] ->
|
[#{tlv_resource_with_value := Id, value := Value}] ->
|
||||||
TrueBaseName = basename(BaseName, undefined, undefined, Id, 3),
|
TrueBaseName = basename(BaseName, undefined, undefined, Id, 3),
|
||||||
|
@ -318,7 +318,7 @@ path([H | T], Acc) ->
|
||||||
|
|
||||||
text_to_json(BaseName, Text) ->
|
text_to_json(BaseName, Text) ->
|
||||||
{ObjectId, ResourceId} = object_resource_id(BaseName),
|
{ObjectId, ResourceId} = object_resource_id(BaseName),
|
||||||
ObjDefinition = emqx_lwm2m_xml_object:get_obj_def(ObjectId, true),
|
ObjDefinition = emqx_lwm2m_xml_object:get_obj_def_assertive(ObjectId, true),
|
||||||
Val = text_value(Text, ResourceId, ObjDefinition),
|
Val = text_value(Text, ResourceId, ObjDefinition),
|
||||||
[#{path => BaseName, value => Val}].
|
[#{path => BaseName, value => Val}].
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
get_obj_def/2,
|
get_obj_def/2,
|
||||||
|
get_obj_def_assertive/2,
|
||||||
get_object_id/1,
|
get_object_id/1,
|
||||||
get_object_name/1,
|
get_object_name/1,
|
||||||
get_object_and_resource_id/2,
|
get_object_and_resource_id/2,
|
||||||
|
@ -29,7 +30,13 @@
|
||||||
get_resource_operations/2
|
get_resource_operations/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
% This module is for future use. Disabled now.
|
get_obj_def_assertive(ObjectId, IsInt) ->
|
||||||
|
case get_obj_def(ObjectId, IsInt) of
|
||||||
|
{error, no_xml_definition} ->
|
||||||
|
erlang:throw({bad_request, {unknown_object_id, ObjectId}});
|
||||||
|
Xml ->
|
||||||
|
Xml
|
||||||
|
end.
|
||||||
|
|
||||||
get_obj_def(ObjectIdInt, true) ->
|
get_obj_def(ObjectIdInt, true) ->
|
||||||
emqx_lwm2m_xml_object_db:find_objectid(ObjectIdInt);
|
emqx_lwm2m_xml_object_db:find_objectid(ObjectIdInt);
|
||||||
|
|
|
@ -76,12 +76,9 @@ find_name(Name) ->
|
||||||
end,
|
end,
|
||||||
case ets:lookup(?LWM2M_OBJECT_NAME_TO_ID_TAB, NameBinary) of
|
case ets:lookup(?LWM2M_OBJECT_NAME_TO_ID_TAB, NameBinary) of
|
||||||
[] ->
|
[] ->
|
||||||
undefined;
|
{error, no_xml_definition};
|
||||||
[{NameBinary, ObjectId}] ->
|
[{NameBinary, ObjectId}] ->
|
||||||
case ets:lookup(?LWM2M_OBJECT_DEF_TAB, ObjectId) of
|
find_objectid(ObjectId)
|
||||||
[] -> undefined;
|
|
||||||
[{ObjectId, Xml}] -> Xml
|
|
||||||
end
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
stop() ->
|
stop() ->
|
||||||
|
|
|
@ -850,6 +850,75 @@ case10_read(Config) ->
|
||||||
),
|
),
|
||||||
?assertEqual(ReadResult, test_recv_mqtt_response(RespTopic)).
|
?assertEqual(ReadResult, test_recv_mqtt_response(RespTopic)).
|
||||||
|
|
||||||
|
case10_read_bad_request(Config) ->
|
||||||
|
UdpSock = ?config(sock, Config),
|
||||||
|
Epn = "urn:oma:lwm2m:oma:3",
|
||||||
|
MsgId1 = 15,
|
||||||
|
RespTopic = list_to_binary("lwm2m/" ++ Epn ++ "/up/resp"),
|
||||||
|
emqtt:subscribe(?config(emqx_c, Config), RespTopic, qos0),
|
||||||
|
timer:sleep(200),
|
||||||
|
% step 1, device register ...
|
||||||
|
test_send_coap_request(
|
||||||
|
UdpSock,
|
||||||
|
post,
|
||||||
|
sprintf("coap://127.0.0.1:~b/rd?ep=~s<=345&lwm2m=1", [?PORT, Epn]),
|
||||||
|
#coap_content{
|
||||||
|
content_format = <<"text/plain">>,
|
||||||
|
payload =
|
||||||
|
<<"</lwm2m>;rt=\"oma.lwm2m\";ct=11543,</lwm2m/1/0>,</lwm2m/2/0>,</lwm2m/3/0>">>
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
MsgId1
|
||||||
|
),
|
||||||
|
#coap_message{method = Method1} = test_recv_coap_response(UdpSock),
|
||||||
|
?assertEqual({ok, created}, Method1),
|
||||||
|
test_recv_mqtt_response(RespTopic),
|
||||||
|
|
||||||
|
% step2, send a READ command to device
|
||||||
|
CmdId = 206,
|
||||||
|
CommandTopic = <<"lwm2m/", (list_to_binary(Epn))/binary, "/dn/dm">>,
|
||||||
|
Command = #{
|
||||||
|
<<"requestID">> => CmdId,
|
||||||
|
<<"cacheID">> => CmdId,
|
||||||
|
<<"msgType">> => <<"read">>,
|
||||||
|
<<"data">> => #{
|
||||||
|
<<"path">> => <<"/3333/0/0">>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CommandJson = emqx_json:encode(Command),
|
||||||
|
?LOGT("CommandJson=~p", [CommandJson]),
|
||||||
|
test_mqtt_broker:publish(CommandTopic, CommandJson, 0),
|
||||||
|
timer:sleep(50),
|
||||||
|
Request2 = test_recv_coap_request(UdpSock),
|
||||||
|
#coap_message{method = Method2, payload = Payload2} = Request2,
|
||||||
|
?LOGT("LwM2M client got ~p", [Request2]),
|
||||||
|
?assertEqual(get, Method2),
|
||||||
|
?assertEqual(<<>>, Payload2),
|
||||||
|
timer:sleep(50),
|
||||||
|
|
||||||
|
test_send_coap_response(
|
||||||
|
UdpSock,
|
||||||
|
"127.0.0.1",
|
||||||
|
?PORT,
|
||||||
|
{ok, content},
|
||||||
|
#coap_content{content_format = <<"text/plain">>, payload = <<"EMQ">>},
|
||||||
|
Request2,
|
||||||
|
true
|
||||||
|
),
|
||||||
|
timer:sleep(100),
|
||||||
|
|
||||||
|
ReadResult = emqx_json:encode(#{
|
||||||
|
<<"requestID">> => CmdId,
|
||||||
|
<<"cacheID">> => CmdId,
|
||||||
|
<<"msgType">> => <<"read">>,
|
||||||
|
<<"data">> => #{
|
||||||
|
<<"code">> => <<"4.00">>,
|
||||||
|
<<"codeMsg">> => <<"bad_request">>,
|
||||||
|
<<"reqPath">> => <<"/3333/0/0">>
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
?assertEqual(ReadResult, test_recv_mqtt_response(RespTopic)).
|
||||||
|
|
||||||
case10_read_separate_ack(Config) ->
|
case10_read_separate_ack(Config) ->
|
||||||
UdpSock = ?config(sock, Config),
|
UdpSock = ?config(sock, Config),
|
||||||
Epn = "urn:oma:lwm2m:oma:3",
|
Epn = "urn:oma:lwm2m:oma:3",
|
||||||
|
|
Loading…
Reference in New Issue