From 1245007c2f6b2c7531e95d1575c0217d2d5c7923 Mon Sep 17 00:00:00 2001 From: Song Guo Date: Wed, 14 Apr 2021 17:48:26 +0800 Subject: [PATCH] Run Codegen --- .../gen/IMClusterCommandHandler.cpp | 5733 ++++++----------- .../all-clusters-common/gen/endpoint_config.h | 2 +- .../gen/IMClusterCommandHandler.cpp | 1419 ++-- .../chip-tool/gen/IMClusterCommandHandler.cpp | 3267 +++------- .../gen/IMClusterCommandHandler.cpp | 1419 ++-- .../gen/IMClusterCommandHandler.cpp | 836 +-- .../main/gen/IMClusterCommandHandler.cpp | 812 +-- .../tv-common/gen/IMClusterCommandHandler.cpp | 5434 +++++----------- .../common/gen/IMClusterCommandHandler.cpp | 236 +- src/controller/CHIPClusters.cpp | 580 -- .../python/gen/IMClusterCommandHandler.cpp | 2702 +++----- .../CHIP/gen/IMClusterCommandHandler.cpp | 3267 +++------- 12 files changed, 8095 insertions(+), 17612 deletions(-) diff --git a/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp b/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp index 11076ed84e8b63..c655dab851f42a 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp +++ b/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp @@ -43,48 +43,58 @@ namespace BarrierControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_BARRIER_CONTROL_GO_TO_PERCENT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t percentOpen; - bool percentOpenExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (percentOpenExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(percentOpen); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - percentOpenExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(percentOpen); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -92,24 +102,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfBarrierControlClusterBarrierControlGoToPercentCallback(percentOpen); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -117,6 +115,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfBarrierControlClusterBarrierControlStopCallback(); + return; break; } default: { @@ -124,10 +123,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_BARRIER_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace BarrierControl @@ -136,6 +145,15 @@ namespace Basic { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -144,10 +162,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_BASIC_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 4, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Basic @@ -156,96 +184,70 @@ namespace Binding { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_BIND_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::NodeId nodeId; - bool nodeIdExists = false; chip::GroupId groupId; - bool groupIdExists = false; chip::EndpointId endpointId; - bool endpointIdExists = false; chip::ClusterId clusterId; - bool clusterIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (nodeIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(nodeId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - nodeIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(nodeId); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (endpointIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endpointId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endpointIdExists = true; - validArgumentCount++; - } break; case 3: - if (clusterIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(clusterId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - clusterIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -253,114 +255,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfBindingClusterBindCallback(nodeId, groupId, endpointId, clusterId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNBIND_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::NodeId nodeId; - bool nodeIdExists = false; chip::GroupId groupId; - bool groupIdExists = false; chip::EndpointId endpointId; - bool endpointIdExists = false; chip::ClusterId clusterId; - bool clusterIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (nodeIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(nodeId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - nodeIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(nodeId); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (endpointIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endpointId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endpointIdExists = true; - validArgumentCount++; - } break; case 3: - if (clusterIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(clusterId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - clusterIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -368,24 +323,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfBindingClusterUnbindCallback(nodeId, groupId, endpointId, clusterId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -394,10 +337,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_BINDING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 4, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Binding @@ -406,96 +359,70 @@ namespace ColorControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_MOVE_COLOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; int16_t rateX; - bool rateXExists = false; int16_t rateY; - bool rateYExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (rateXExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(rateX); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - rateXExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(rateX); break; case 1: - if (rateYExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rateY); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateYExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -503,146 +430,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveColorCallback(rateX, rateY, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_COLOR_TEMPERATURE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint8_t moveMode; - bool moveModeExists = false; uint16_t rate; - bool rateExists = false; uint16_t colorTemperatureMinimum; - bool colorTemperatureMinimumExists = false; uint16_t colorTemperatureMaximum; - bool colorTemperatureMaximumExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (colorTemperatureMinimumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMinimumExists = true; - validArgumentCount++; - } break; case 3: - if (colorTemperatureMaximumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMaximumExists = true; - validArgumentCount++; - } break; case 4: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 5: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -650,115 +506,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveColorTemperatureCallback(moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_HUE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -766,114 +575,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveHueCallback(moveMode, rate, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_SATURATION_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -881,130 +643,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveSaturationCallback(moveMode, rate, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_COLOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint16_t colorX; - bool colorXExists = false; uint16_t colorY; - bool colorYExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (colorXExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(colorX); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - colorXExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(colorX); break; case 1: - if (colorYExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorY); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorYExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1012,114 +715,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToColorCallback(colorX, colorY, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_COLOR_TEMPERATURE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t colorTemperature; - bool colorTemperatureExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (colorTemperatureExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(colorTemperature); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - colorTemperatureExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(colorTemperature); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1127,131 +783,72 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToColorTemperatureCallback(colorTemperature, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_HUE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t hue; - bool hueExists = false; uint8_t direction; - bool directionExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (hueExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(hue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - hueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(hue); break; case 1: - if (directionExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(direction); - if (CHIP_NO_ERROR == TLVUnpackError) - { - directionExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1259,130 +856,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToHueCallback(hue, direction, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_HUE_AND_SATURATION_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t hue; - bool hueExists = false; uint8_t saturation; - bool saturationExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (hueExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(hue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - hueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(hue); break; case 1: - if (saturationExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(saturation); - if (CHIP_NO_ERROR == TLVUnpackError) - { - saturationExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1390,115 +928,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToHueAndSaturationCallback(hue, saturation, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_SATURATION_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t saturation; - bool saturationExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (saturationExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(saturation); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - saturationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(saturation); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1506,130 +997,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToSaturationCallback(saturation, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_COLOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; int16_t stepX; - bool stepXExists = false; int16_t stepY; - bool stepYExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepXExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepX); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepXExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepX); break; case 1: - if (stepYExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepY); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepYExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1637,162 +1069,79 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStepColorCallback(stepX, stepY, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_COLOR_TEMPERATURE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint8_t stepMode; - bool stepModeExists = false; uint16_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint16_t colorTemperatureMinimum; - bool colorTemperatureMinimumExists = false; uint16_t colorTemperatureMaximum; - bool colorTemperatureMaximumExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 7) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (colorTemperatureMinimumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMinimumExists = true; - validArgumentCount++; - } break; case 4: - if (colorTemperatureMaximumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMaximumExists = true; - validArgumentCount++; - } break; case 5: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 6: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1800,131 +1149,72 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStepColorTemperatureCallback(stepMode, stepSize, transitionTime, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_HUE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint8_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1932,130 +1222,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStepHueCallback(stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_SATURATION_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint8_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2063,82 +1294,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStepSaturationCallback(stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STOP_MOVE_STEP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (optionsMaskExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionsMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionsMask); break; case 1: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2146,24 +1354,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStopMoveStepCallback(optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2172,10 +1368,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_COLOR_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace ColorControl @@ -2184,6 +1390,15 @@ namespace DoorLock { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -2191,53 +1406,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllPinsCallback(); + return; break; } case ZCL_CLEAR_ALL_RFIDS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllRfidsCallback(); + return; break; } case ZCL_CLEAR_HOLIDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t scheduleId; - bool scheduleIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2245,66 +1463,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearHolidayScheduleCallback(scheduleId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_PIN_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2312,66 +1519,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearPinCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_RFID_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2379,82 +1575,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearRfidCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_WEEKDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2462,82 +1635,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearWeekdayScheduleCallback(scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_YEARDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2545,66 +1695,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearYeardayScheduleCallback(scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_HOLIDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t scheduleId; - bool scheduleIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2612,66 +1751,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetHolidayScheduleCallback(scheduleId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LOG_RECORD_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t logIndex; - bool logIndexExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (logIndexExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(logIndex); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - logIndexExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(logIndex); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2679,66 +1807,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetLogRecordCallback(logIndex); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_PIN_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2746,66 +1863,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetPinCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_RFID_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2813,66 +1919,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetRfidCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_USER_TYPE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2880,82 +1975,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetUserTypeCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_WEEKDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2963,82 +2035,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetWeekdayScheduleCallback(scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_YEARDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3046,67 +2095,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetYeardayScheduleCallback(scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_LOCK_DOOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * PIN; - bool PINExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (PINExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(PIN); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - PINExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(PIN); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3114,114 +2152,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterLockDoorCallback(const_cast(PIN)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_HOLIDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t scheduleId; - bool scheduleIdExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; uint8_t operatingModeDuringHoliday; - bool operatingModeDuringHolidayExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) - { - case 0: - if (scheduleIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - scheduleIdExists = true; - validArgumentCount++; - } - break; - case 1: - if (localStartTimeExists) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - localStartTimeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); + break; + case 1: + TLVUnpackError = aDataTlv.Get(localStartTime); break; case 2: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; case 3: - if (operatingModeDuringHolidayExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - if (CHIP_NO_ERROR == TLVUnpackError) - { - operatingModeDuringHolidayExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3229,116 +2220,69 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetHolidayScheduleCallback(scheduleId, localStartTime, localEndTime, operatingModeDuringHoliday); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_PIN_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3346,115 +2290,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetPinCallback(userId, userStatus, userType, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_RFID_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * id; - bool idExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (idExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(id); - if (CHIP_NO_ERROR == TLVUnpackError) - { - idExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3462,82 +2359,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetRfidCallback(userId, userStatus, userType, const_cast(id)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_USER_TYPE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t userId; - bool userIdExists = false; uint8_t userType; - bool userTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3545,162 +2419,79 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetUserTypeCallback(userId, userType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_WEEKDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t daysMask; - bool daysMaskExists = false; uint8_t startHour; - bool startHourExists = false; uint8_t startMinute; - bool startMinuteExists = false; uint8_t endHour; - bool endHourExists = false; uint8_t endMinute; - bool endMinuteExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 7) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (daysMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(daysMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - daysMaskExists = true; - validArgumentCount++; - } break; case 3: - if (startHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startHourExists = true; - validArgumentCount++; - } break; case 4: - if (startMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startMinuteExists = true; - validArgumentCount++; - } break; case 5: - if (endHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endHourExists = true; - validArgumentCount++; - } break; case 6: - if (endMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endMinuteExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3708,115 +2499,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetWeekdayScheduleCallback(scheduleId, userId, daysMask, startHour, startMinute, endHour, endMinute); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_YEARDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 3: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3824,67 +2568,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetYeardayScheduleCallback(scheduleId, userId, localStartTime, localEndTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_DOOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * PIN; - bool PINExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (PINExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(PIN); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - PINExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(PIN); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3892,83 +2625,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockDoorCallback(const_cast(PIN)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_WITH_TIMEOUT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t timeoutInSeconds; - bool timeoutInSecondsExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutInSecondsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutInSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutInSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutInSeconds); break; case 1: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3976,24 +2686,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockWithTimeoutCallback(timeoutInSeconds, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4002,10 +2700,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -4014,80 +2722,66 @@ namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t expiryLengthSeconds; - bool expiryLengthSecondsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (expiryLengthSecondsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - expiryLengthSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(expiryLengthSeconds); break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4095,24 +2789,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterArmFailSafeCallback(expiryLengthSeconds, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4120,103 +2802,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterCommissioningCompleteCallback(); + return; break; } case ZCL_SET_FABRIC_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan fabricId; - bool fabricIdExists = false; chip::ByteSpan fabricSecret; - bool fabricSecretExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (fabricIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - fabricId = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - fabricIdExists = true; - validArgumentCount++; - } - break; - case 1: - if (fabricSecretExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - fabricSecret = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - fabricSecretExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + fabricId = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + fabricSecret = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4224,24 +2870,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterSetFabricCallback(fabricId, fabricSecret, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4250,10 +2884,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -4262,65 +2906,63 @@ namespace Groups { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_GROUP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4328,83 +2970,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterAddGroupCallback(groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_GROUP_IF_IDENTIFYING_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4412,83 +3031,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterAddGroupIfIdentifyingCallback(groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_GROUP_MEMBERSHIP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupCountExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupCountExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupCount); break; case 1: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4496,24 +3092,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterGetGroupMembershipCallback(groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4521,47 +3105,49 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterRemoveAllGroupsCallback(); + return; break; } case ZCL_REMOVE_GROUP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4569,66 +3155,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterRemoveGroupCallback(groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_GROUP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4636,24 +3211,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterViewGroupCallback(groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4662,10 +3225,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -4674,64 +3247,62 @@ namespace IasZone { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ZONE_ENROLL_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t enrollResponseCode; - bool enrollResponseCodeExists = false; uint8_t zoneId; - bool zoneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (enrollResponseCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(enrollResponseCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - enrollResponseCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(enrollResponseCode); break; case 1: - if (zoneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(zoneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - zoneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4739,24 +3310,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfIasZoneClusterZoneEnrollResponseCallback(enrollResponseCode, zoneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4765,10 +3324,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IAS_ZONE_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 5, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace IasZone @@ -4777,48 +3346,58 @@ namespace Identify { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_IDENTIFY_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t identifyTime; - bool identifyTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) { - case 0: - if (identifyTimeExists) + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(identifyTime); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - identifyTimeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(identifyTime); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4826,24 +3405,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfIdentifyClusterIdentifyCallback(identifyTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4851,6 +3418,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfIdentifyClusterIdentifyQueryCallback(); + return; break; } default: { @@ -4858,10 +3426,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -4870,96 +3448,70 @@ namespace LevelControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_MOVE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4967,114 +3519,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveCallback(moveMode, rate, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_LEVEL_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (levelExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5082,82 +3587,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveToLevelCallback(level, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (levelExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5165,82 +3647,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveToLevelWithOnOffCallback(level, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5248,130 +3707,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveWithOnOffCallback(moveMode, rate); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5379,98 +3779,63 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStepCallback(stepMode, stepSize, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5478,82 +3843,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStepWithOnOffCallback(stepMode, stepSize, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STOP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (optionMaskExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionMask); break; case 1: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5561,24 +3903,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStopCallback(optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -5586,6 +3916,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStopWithOnOffCallback(); + return; break; } default: { @@ -5593,10 +3924,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LEVEL_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LevelControl @@ -5605,6 +3946,15 @@ namespace LowPower { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -5612,6 +3962,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLowPowerClusterSleepCallback(); + return; break; } default: { @@ -5619,10 +3970,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LOW_POWER_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LowPower @@ -5631,84 +3992,69 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5716,122 +4062,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5839,102 +4136,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5942,102 +4203,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterDisableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6045,66 +4270,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterEnableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutMsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6112,102 +4326,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (NetworkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6215,102 +4393,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterRemoveNetworkCallback(NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6318,102 +4460,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterScanNetworksCallback(ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; - case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } + case 2: TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6421,122 +4527,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6544,24 +4601,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -6570,10 +4615,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -6582,6 +4637,15 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -6589,18 +4653,21 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOffCallback(); + return; break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOnCallback(); + return; break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterToggleCallback(); + return; break; } default: { @@ -6608,10 +4675,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 5, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff @@ -6620,114 +4697,76 @@ namespace Scenes { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 4: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6735,67 +4774,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterAddSceneCallback(groupId, sceneId, transitionTime, const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_SCENE_MEMBERSHIP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6803,98 +4831,63 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterGetSceneMembershipCallback(groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_RECALL_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6902,66 +4895,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRecallSceneCallback(groupId, sceneId, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_ALL_SCENES_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6969,82 +4951,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveAllScenesCallback(groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -7052,82 +5011,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveSceneCallback(groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STORE_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -7135,82 +5071,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterStoreSceneCallback(groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -7218,24 +5131,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterViewSceneCallback(groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -7244,10 +5145,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes diff --git a/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h b/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h index c2dfa1414f0e3c..37a1151c6c688a 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h +++ b/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h @@ -468,8 +468,8 @@ { 0x0000, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(0) }, /* Descriptor (server): device list */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(254) }, /* Descriptor (server): server list */ \ { 0x0002, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(508) }, /* Descriptor (server): client list */ \ - { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* Descriptor (server): cluster revision */ \ { 0x0003, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(762) }, /* Descriptor (server): parts list */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* Descriptor (server): cluster revision */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(SINGLETON), \ ZAP_SIMPLE_DEFAULT(3) }, /* Basic (server): cluster revision */ \ { 0x0000, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(SINGLETON), \ diff --git a/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp b/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp index 517ede632664ad..6cae9ceedc2e80 100644 --- a/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp +++ b/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp @@ -43,96 +43,70 @@ namespace LevelControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_MOVE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -140,114 +114,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveCallback(moveMode, rate, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_LEVEL_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (levelExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -255,82 +182,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveToLevelCallback(level, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (levelExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -338,82 +242,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveToLevelWithOnOffCallback(level, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -421,130 +302,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveWithOnOffCallback(moveMode, rate); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -552,98 +374,63 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStepCallback(stepMode, stepSize, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -651,82 +438,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStepWithOnOffCallback(stepMode, stepSize, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STOP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (optionMaskExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionMask); break; case 1: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -734,24 +498,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStopCallback(optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -759,6 +511,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStopWithOnOffCallback(); + return; break; } default: { @@ -766,10 +519,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LEVEL_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LevelControl @@ -778,84 +541,69 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -863,122 +611,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; - validArgumentCount++; - } - break; - case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } - break; - case 3: - if (timeoutMsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(breadcrumb); + break; + case 3: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -986,102 +685,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1089,102 +752,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterDisableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1192,66 +819,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterEnableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutMsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1259,102 +875,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (NetworkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1362,102 +942,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterRemoveNetworkCallback(NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1465,102 +1009,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterScanNetworksCallback(ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1568,122 +1076,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1691,24 +1150,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -1717,10 +1164,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -1729,6 +1186,15 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -1736,18 +1202,21 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOffCallback(); + return; break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOnCallback(); + return; break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterToggleCallback(); + return; break; } default: { @@ -1755,10 +1224,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 5, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff diff --git a/examples/chip-tool/gen/IMClusterCommandHandler.cpp b/examples/chip-tool/gen/IMClusterCommandHandler.cpp index 96a8be3f1c5de1..0b69c6f8e7e5a0 100644 --- a/examples/chip-tool/gen/IMClusterCommandHandler.cpp +++ b/examples/chip-tool/gen/IMClusterCommandHandler.cpp @@ -43,48 +43,58 @@ namespace DoorLock { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_CLEAR_ALL_PINS_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -92,66 +102,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllPinsResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -159,66 +158,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllRfidsResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -226,66 +214,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearHolidayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -293,66 +270,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearPinResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -360,66 +326,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearRfidResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -427,66 +382,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -494,130 +438,71 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearYeardayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; uint8_t operatingModeDuringHoliday; - bool operatingModeDuringHolidayExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 2: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 3: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; case 4: - if (operatingModeDuringHolidayExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - if (CHIP_NO_ERROR == TLVUnpackError) - { - operatingModeDuringHolidayExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -625,164 +510,81 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetHolidayScheduleResponseCallback(scheduleId, status, localStartTime, localEndTime, operatingModeDuringHoliday); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint16_t logEntryId; - bool logEntryIdExists = false; uint32_t timestamp; - bool timestampExists = false; uint8_t eventType; - bool eventTypeExists = false; uint8_t source; - bool sourceExists = false; uint8_t eventIdOrAlarmCode; - bool eventIdOrAlarmCodeExists = false; uint16_t userId; - bool userIdExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (logEntryIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 7) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(logEntryId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - logEntryIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(logEntryId); break; case 1: - if (timestampExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timestamp); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timestampExists = true; - validArgumentCount++; - } break; case 2: - if (eventTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventTypeExists = true; - validArgumentCount++; - } break; case 3: - if (sourceExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(source); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sourceExists = true; - validArgumentCount++; - } break; case 4: - if (eventIdOrAlarmCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventIdOrAlarmCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventIdOrAlarmCodeExists = true; - validArgumentCount++; - } break; case 5: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 6: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -790,116 +592,69 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetLogRecordResponseCallback(logEntryId, timestamp, eventType, source, eventIdOrAlarmCode, userId, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_PIN_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -907,115 +662,68 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetPinResponseCallback(userId, userStatus, userType, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_RFID_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * rfid; - bool rfidExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (rfidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(rfid); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rfidExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1023,82 +731,59 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetRfidResponseCallback(userId, userStatus, userType, const_cast(rfid)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t userId; - bool userIdExists = false; uint8_t userType; - bool userTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1106,178 +791,83 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetUserTypeResponseCallback(userId, userType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 8; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint8_t daysMask; - bool daysMaskExists = false; uint8_t startHour; - bool startHourExists = false; uint8_t startMinute; - bool startMinuteExists = false; uint8_t endHour; - bool endHourExists = false; uint8_t endMinute; - bool endMinuteExists = false; - uint32_t validArgumentCount = 0; + bool argExists[8]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 8) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (daysMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(daysMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - daysMaskExists = true; - validArgumentCount++; - } break; case 4: - if (startHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startHourExists = true; - validArgumentCount++; - } break; case 5: - if (startMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startMinuteExists = true; - validArgumentCount++; - } break; case 6: - if (endHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endHourExists = true; - validArgumentCount++; - } break; case 7: - if (endMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endMinuteExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1285,131 +875,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 8 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(scheduleId, userId, status, daysMask, startHour, startMinute, endHour, endMinute); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 8, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 4: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1417,66 +948,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetYeardayScheduleResponseCallback(scheduleId, userId, status, localStartTime, localEndTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1484,66 +1004,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterLockDoorResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1551,66 +1060,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetHolidayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_PIN_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1618,66 +1116,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetPinResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_RFID_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1685,66 +1172,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetRfidResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1752,66 +1228,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetUserTypeResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1819,66 +1284,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1886,66 +1340,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetYeardayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1953,66 +1396,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockDoorResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2020,24 +1452,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2046,10 +1466,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -2058,65 +1488,63 @@ namespace GeneralCommissioning { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2124,83 +1552,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_COMMISSIONING_COMPLETE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2208,84 +1613,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_FABRIC_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2293,24 +1675,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterSetFabricResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2319,10 +1689,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 5, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -2331,64 +1711,62 @@ namespace Groups { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_GROUP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2396,99 +1774,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterAddGroupResponseCallback(status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t capacity; - bool capacityExists = false; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (capacityExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - capacityExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(capacity); break; case 1: - if (groupCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupCountExists = true; - validArgumentCount++; - } break; case 2: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2496,82 +1839,59 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterGetGroupMembershipResponseCallback(capacity, groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2579,99 +1899,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterRemoveGroupResponseCallback(status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2679,24 +1964,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterViewGroupResponseCallback(status, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2705,10 +1978,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -2717,48 +2000,58 @@ namespace Identify { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_IDENTIFY_QUERY_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t timeout; - bool timeoutExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeout); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeout); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2766,24 +2059,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfIdentifyClusterIdentifyQueryResponseCallback(timeout); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2792,10 +2073,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -2804,65 +2095,63 @@ namespace NetworkCommissioning { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2870,83 +2159,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2954,83 +2220,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3038,83 +2281,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ENABLE_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3122,83 +2342,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3206,117 +2403,70 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SCAN_NETWORKS_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults; - bool wifiScanResultsExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults; - bool threadScanResultsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; case 2: - if (wifiScanResultsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(wifiScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - wifiScanResultsExists = true; - validArgumentCount++; - } break; case 3: - if (threadScanResultsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(threadScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - threadScanResultsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3324,84 +2474,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterScanNetworksResponseCallback(errorCode, const_cast(debugText), wifiScanResults, threadScanResults); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_THREAD_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3409,83 +2536,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3493,24 +2597,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -3519,10 +2611,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -3531,80 +2633,66 @@ namespace Scenes { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3612,131 +2700,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterAddSceneResponseCallback(status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t status; - bool statusExists = false; uint8_t capacity; - bool capacityExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneCount; - bool sceneCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * sceneList; - bool sceneListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (capacityExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) - { - capacityExists = true; - validArgumentCount++; - } break; case 2: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 3: - if (sceneCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneCountExists = true; - validArgumentCount++; - } break; case 4: - if (sceneListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(sceneList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3744,82 +2773,59 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterGetSceneMembershipResponseCallback(status, capacity, groupId, sceneCount, sceneList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3827,98 +2833,63 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveAllScenesResponseCallback(status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3926,98 +2897,63 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveSceneResponseCallback(status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STORE_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4025,148 +2961,77 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterStoreSceneResponseCallback(status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 3: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 4: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 5: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4174,25 +3039,13 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterViewSceneResponseCallback(status, groupId, sceneId, transitionTime, const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4201,10 +3054,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 3, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes diff --git a/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp b/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp index 517ede632664ad..a881c13a9a0e05 100644 --- a/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp +++ b/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp @@ -43,96 +43,70 @@ namespace LevelControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_MOVE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -140,114 +114,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveCallback(moveMode, rate, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_LEVEL_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (levelExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -255,82 +182,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveToLevelCallback(level, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (levelExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -338,82 +242,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveToLevelWithOnOffCallback(level, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -421,130 +302,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveWithOnOffCallback(moveMode, rate); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -552,98 +374,63 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStepCallback(stepMode, stepSize, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -651,82 +438,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStepWithOnOffCallback(stepMode, stepSize, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STOP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (optionMaskExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionMask); break; case 1: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -734,24 +498,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStopCallback(optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -759,6 +511,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStopWithOnOffCallback(); + return; break; } default: { @@ -766,10 +519,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LEVEL_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 4, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LevelControl @@ -778,84 +541,69 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -863,122 +611,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; - validArgumentCount++; - } - break; - case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } - break; - case 3: - if (timeoutMsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(breadcrumb); + break; + case 3: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -986,102 +685,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1089,102 +752,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterDisableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1192,66 +819,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterEnableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutMsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1259,102 +875,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (NetworkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1362,102 +942,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterRemoveNetworkCallback(NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1465,102 +1009,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterScanNetworksCallback(ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1568,122 +1076,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1691,24 +1150,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -1717,10 +1164,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -1729,6 +1186,15 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -1736,18 +1202,21 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOffCallback(); + return; break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOnCallback(); + return; break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterToggleCallback(); + return; break; } default: { @@ -1755,10 +1224,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff diff --git a/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp b/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp index e8cc481cfb81d5..b313b567c9787d 100644 --- a/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp +++ b/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp @@ -43,84 +43,69 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -128,122 +113,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -251,102 +187,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -354,102 +254,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterDisableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -457,66 +321,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterEnableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutMsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -524,102 +377,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (NetworkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -627,102 +444,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterRemoveNetworkCallback(NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -730,102 +511,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterScanNetworksCallback(ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -833,122 +578,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; - case 1: - if (credentialsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; - validArgumentCount++; - } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -956,24 +652,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -982,10 +666,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -994,6 +688,15 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -1001,18 +704,21 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOffCallback(); + return; break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOnCallback(); + return; break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterToggleCallback(); + return; break; } default: { @@ -1020,10 +726,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 5, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff diff --git a/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp b/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp index ae9c40556bf518..8638e86a8c77e0 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp +++ b/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp @@ -43,84 +43,69 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -128,122 +113,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -251,102 +187,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -354,102 +254,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterDisableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -457,66 +321,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterEnableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutMsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -524,102 +377,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (NetworkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -627,102 +444,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterRemoveNetworkCallback(NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -730,102 +511,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterScanNetworksCallback(ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -833,122 +578,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -956,24 +652,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -982,10 +666,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning diff --git a/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp b/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp index 75ef4d072187c1..8dab8114383b5f 100644 --- a/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp +++ b/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp @@ -43,48 +43,58 @@ namespace BarrierControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_BARRIER_CONTROL_GO_TO_PERCENT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t percentOpen; - bool percentOpenExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (percentOpenExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(percentOpen); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - percentOpenExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(percentOpen); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -92,24 +102,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfBarrierControlClusterBarrierControlGoToPercentCallback(percentOpen); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -117,6 +115,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfBarrierControlClusterBarrierControlStopCallback(); + return; break; } default: { @@ -124,10 +123,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_BARRIER_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace BarrierControl @@ -136,96 +145,70 @@ namespace ColorControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_MOVE_COLOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; int16_t rateX; - bool rateXExists = false; int16_t rateY; - bool rateYExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (rateXExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(rateX); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - rateXExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(rateX); break; case 1: - if (rateYExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rateY); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateYExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -233,146 +216,75 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveColorCallback(rateX, rateY, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_COLOR_TEMPERATURE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint8_t moveMode; - bool moveModeExists = false; uint16_t rate; - bool rateExists = false; uint16_t colorTemperatureMinimum; - bool colorTemperatureMinimumExists = false; uint16_t colorTemperatureMaximum; - bool colorTemperatureMaximumExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (colorTemperatureMinimumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMinimumExists = true; - validArgumentCount++; - } break; case 3: - if (colorTemperatureMaximumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMaximumExists = true; - validArgumentCount++; - } break; case 4: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 5: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -380,115 +292,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveColorTemperatureCallback(moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_HUE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -496,114 +361,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveHueCallback(moveMode, rate, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_SATURATION_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -611,130 +429,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveSaturationCallback(moveMode, rate, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_COLOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint16_t colorX; - bool colorXExists = false; uint16_t colorY; - bool colorYExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (colorXExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(colorX); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - colorXExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(colorX); break; case 1: - if (colorYExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorY); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorYExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -742,114 +501,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToColorCallback(colorX, colorY, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_COLOR_TEMPERATURE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t colorTemperature; - bool colorTemperatureExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (colorTemperatureExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(colorTemperature); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - colorTemperatureExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(colorTemperature); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -857,131 +569,72 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToColorTemperatureCallback(colorTemperature, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_HUE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t hue; - bool hueExists = false; uint8_t direction; - bool directionExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (hueExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(hue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - hueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(hue); break; case 1: - if (directionExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(direction); - if (CHIP_NO_ERROR == TLVUnpackError) - { - directionExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -989,130 +642,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToHueCallback(hue, direction, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_HUE_AND_SATURATION_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t hue; - bool hueExists = false; uint8_t saturation; - bool saturationExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (hueExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(hue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - hueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(hue); break; case 1: - if (saturationExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(saturation); - if (CHIP_NO_ERROR == TLVUnpackError) - { - saturationExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1120,115 +714,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToHueAndSaturationCallback(hue, saturation, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_SATURATION_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t saturation; - bool saturationExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (saturationExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(saturation); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - saturationExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(saturation); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1236,130 +783,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterMoveToSaturationCallback(saturation, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_COLOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; int16_t stepX; - bool stepXExists = false; int16_t stepY; - bool stepYExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepXExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepX); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepXExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepX); break; case 1: - if (stepYExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepY); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepYExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1367,162 +855,79 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStepColorCallback(stepX, stepY, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_COLOR_TEMPERATURE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint8_t stepMode; - bool stepModeExists = false; uint16_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint16_t colorTemperatureMinimum; - bool colorTemperatureMinimumExists = false; uint16_t colorTemperatureMaximum; - bool colorTemperatureMaximumExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 7) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (colorTemperatureMinimumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMinimum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMinimumExists = true; - validArgumentCount++; - } break; case 4: - if (colorTemperatureMaximumExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(colorTemperatureMaximum); - if (CHIP_NO_ERROR == TLVUnpackError) - { - colorTemperatureMaximumExists = true; - validArgumentCount++; - } break; case 5: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 6: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1530,131 +935,72 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStepColorTemperatureCallback(stepMode, stepSize, transitionTime, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_HUE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint8_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1662,130 +1008,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStepHueCallback(stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_SATURATION_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint8_t transitionTime; - bool transitionTimeExists = false; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; - case 3: - if (optionsMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsMaskExists = true; - validArgumentCount++; - } + case 3: + TLVUnpackError = aDataTlv.Get(optionsMask); break; case 4: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1793,82 +1080,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStepSaturationCallback(stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STOP_MOVE_STEP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionsMask; - bool optionsMaskExists = false; uint8_t optionsOverride; - bool optionsOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (optionsMaskExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(optionsMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionsMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionsMask); break; case 1: - if (optionsOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionsOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionsOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1876,24 +1140,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfColorControlClusterStopMoveStepCallback(optionsMask, optionsOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -1902,10 +1154,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_COLOR_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace ColorControl @@ -1914,48 +1176,58 @@ namespace DoorLock { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1963,66 +1235,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterLockDoorResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2030,24 +1291,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockDoorResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2056,10 +1305,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -2068,6 +1327,15 @@ namespace DoorLock { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -2075,53 +1343,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllPinsCallback(); + return; break; } case ZCL_CLEAR_ALL_RFIDS_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllRfidsCallback(); + return; break; } case ZCL_CLEAR_HOLIDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t scheduleId; - bool scheduleIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2129,66 +1400,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearHolidayScheduleCallback(scheduleId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_PIN_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2196,66 +1456,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearPinCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_RFID_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2263,82 +1512,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearRfidCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_WEEKDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2346,82 +1572,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearWeekdayScheduleCallback(scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_YEARDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2429,66 +1632,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearYeardayScheduleCallback(scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_HOLIDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t scheduleId; - bool scheduleIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2496,66 +1688,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetHolidayScheduleCallback(scheduleId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LOG_RECORD_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t logIndex; - bool logIndexExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (logIndexExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(logIndex); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - logIndexExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(logIndex); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2563,66 +1744,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetLogRecordCallback(logIndex); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_PIN_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2630,66 +1800,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetPinCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_RFID_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2697,64 +1856,53 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetRfidCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_USER_TYPE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; default: // Unsupported tag, ignore it. - ChipLogProgress(Zcl, "Unknown TLV tag during processing."); - break; - } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } } @@ -2764,82 +1912,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetUserTypeCallback(userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_WEEKDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2847,82 +1972,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetWeekdayScheduleCallback(scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_YEARDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2930,67 +2032,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetYeardayScheduleCallback(scheduleId, userId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_LOCK_DOOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * PIN; - bool PINExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (PINExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(PIN); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - PINExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(PIN); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2998,114 +2089,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterLockDoorCallback(const_cast(PIN)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_HOLIDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t scheduleId; - bool scheduleIdExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; uint8_t operatingModeDuringHoliday; - bool operatingModeDuringHolidayExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 2: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; case 3: - if (operatingModeDuringHolidayExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - if (CHIP_NO_ERROR == TLVUnpackError) - { - operatingModeDuringHolidayExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3113,116 +2157,69 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetHolidayScheduleCallback(scheduleId, localStartTime, localEndTime, operatingModeDuringHoliday); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_PIN_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3230,115 +2227,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetPinCallback(userId, userStatus, userType, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_RFID_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * id; - bool idExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (idExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(id); - if (CHIP_NO_ERROR == TLVUnpackError) - { - idExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3346,82 +2296,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetRfidCallback(userId, userStatus, userType, const_cast(id)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_USER_TYPE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t userId; - bool userIdExists = false; uint8_t userType; - bool userTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3429,162 +2356,79 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetUserTypeCallback(userId, userType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_WEEKDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t daysMask; - bool daysMaskExists = false; uint8_t startHour; - bool startHourExists = false; uint8_t startMinute; - bool startMinuteExists = false; uint8_t endHour; - bool endHourExists = false; uint8_t endMinute; - bool endMinuteExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 7) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (daysMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(daysMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - daysMaskExists = true; - validArgumentCount++; - } break; case 3: - if (startHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - TLVUnpackError = aDataTlv.Get(startHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startHourExists = true; - validArgumentCount++; - } - break; - case 4: - if (startMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } + TLVUnpackError = aDataTlv.Get(startHour); + break; + case 4: TLVUnpackError = aDataTlv.Get(startMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startMinuteExists = true; - validArgumentCount++; - } break; case 5: - if (endHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endHourExists = true; - validArgumentCount++; - } break; case 6: - if (endMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endMinuteExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3592,115 +2436,68 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetWeekdayScheduleCallback(scheduleId, userId, daysMask, startHour, startMinute, endHour, endMinute); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_YEARDAY_SCHEDULE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 3: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3708,67 +2505,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetYeardayScheduleCallback(scheduleId, userId, localStartTime, localEndTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_DOOR_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; const uint8_t * PIN; - bool PINExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (PINExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. - TLVUnpackError = aDataTlv.GetDataPtr(PIN); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - PINExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. + TLVUnpackError = aDataTlv.GetDataPtr(PIN); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3776,83 +2562,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockDoorCallback(const_cast(PIN)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_WITH_TIMEOUT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t timeoutInSeconds; - bool timeoutInSecondsExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutInSecondsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutInSeconds); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutInSecondsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutInSeconds); break; case 1: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3860,24 +2623,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockWithTimeoutCallback(timeoutInSeconds, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -3886,10 +2637,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -3898,65 +2659,63 @@ namespace Groups { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_GROUP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3964,83 +2723,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterAddGroupCallback(groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_GROUP_IF_IDENTIFYING_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4048,83 +2784,60 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterAddGroupIfIdentifyingCallback(groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_GROUP_MEMBERSHIP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupCountExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupCountExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupCount); break; case 1: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4132,24 +2845,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterGetGroupMembershipCallback(groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4157,47 +2858,49 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterRemoveAllGroupsCallback(); + return; break; } case ZCL_REMOVE_GROUP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4205,66 +2908,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterRemoveGroupCallback(groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_GROUP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4272,24 +2964,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterViewGroupCallback(groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4298,10 +2978,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -4310,64 +3000,62 @@ namespace IasZone { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ZONE_ENROLL_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t enrollResponseCode; - bool enrollResponseCodeExists = false; uint8_t zoneId; - bool zoneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (enrollResponseCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(enrollResponseCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - enrollResponseCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(enrollResponseCode); break; case 1: - if (zoneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(zoneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - zoneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4375,24 +3063,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfIasZoneClusterZoneEnrollResponseCallback(enrollResponseCode, zoneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4401,10 +3077,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IAS_ZONE_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 5, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace IasZone @@ -4413,48 +3099,58 @@ namespace Identify { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_IDENTIFY_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t identifyTime; - bool identifyTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) { - case 0: - if (identifyTimeExists) + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(identifyTime); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - identifyTimeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(identifyTime); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4462,24 +3158,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfIdentifyClusterIdentifyCallback(identifyTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4487,6 +3171,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfIdentifyClusterIdentifyQueryCallback(); + return; break; } default: { @@ -4494,10 +3179,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -4506,96 +3201,70 @@ namespace LevelControl { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_MOVE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4603,114 +3272,67 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveCallback(moveMode, rate, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_LEVEL_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (levelExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 2: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 3: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4718,82 +3340,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveToLevelCallback(level, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t level; - bool levelExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (levelExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(level); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - levelExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(level); break; case 1: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4801,82 +3400,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveToLevelWithOnOffCallback(level, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_MOVE_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t moveMode; - bool moveModeExists = false; uint8_t rate; - bool rateExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (moveModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(moveMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - moveModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(moveMode); break; case 1: - if (rateExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(rate); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rateExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4884,130 +3460,71 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterMoveWithOnOffCallback(moveMode, rate); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (optionMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionMaskExists = true; - validArgumentCount++; - } break; case 4: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5015,98 +3532,63 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStepCallback(stepMode, stepSize, transitionTime, optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STEP_WITH_ON_OFF_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t stepMode; - bool stepModeExists = false; uint8_t stepSize; - bool stepSizeExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (stepModeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(stepMode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - stepModeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(stepMode); break; case 1: - if (stepSizeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(stepSize); - if (CHIP_NO_ERROR == TLVUnpackError) - { - stepSizeExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5114,82 +3596,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStepWithOnOffCallback(stepMode, stepSize, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STOP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t optionMask; - bool optionMaskExists = false; uint8_t optionOverride; - bool optionOverrideExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (optionMaskExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(optionMask); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - optionMaskExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(optionMask); break; case 1: - if (optionOverrideExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(optionOverride); - if (CHIP_NO_ERROR == TLVUnpackError) - { - optionOverrideExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5197,24 +3656,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStopCallback(optionMask, optionOverride); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -5222,6 +3669,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLevelControlClusterStopWithOnOffCallback(); + return; break; } default: { @@ -5229,10 +3677,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LEVEL_CONTROL_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LevelControl @@ -5241,6 +3699,15 @@ namespace LowPower { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -5248,6 +3715,7 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfLowPowerClusterSleepCallback(); + return; break; } default: { @@ -5255,10 +3723,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_LOW_POWER_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 3, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace LowPower @@ -5267,84 +3745,69 @@ namespace NetworkCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5352,122 +3815,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5475,102 +3889,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_DISABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5578,102 +3956,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterDisableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ENABLE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan networkID; - bool networkIDExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (networkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - networkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - networkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + networkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5681,66 +4023,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterEnableNetworkCallback(networkID, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutMsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutMsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeoutMs); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5748,102 +4079,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan NetworkID; - bool NetworkIDExists = false; uint64_t Breadcrumb; - bool BreadcrumbExists = false; uint32_t TimeoutMs; - bool TimeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (NetworkIDExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - NetworkIDExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + NetworkID = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (BreadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(Breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - BreadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (TimeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(TimeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - TimeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5851,102 +4146,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterRemoveNetworkCallback(NetworkID, Breadcrumb, TimeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SCAN_NETWORKS_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan ssid; - bool ssidExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -5954,102 +4213,66 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterScanNetworksCallback(ssid, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; chip::ByteSpan operationalDataset; - bool operationalDatasetExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (operationalDatasetExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - operationalDatasetExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 1: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; - case 2: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } + case 2: TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6057,122 +4280,73 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(operationalDataset, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; chip::ByteSpan ssid; - bool ssidExists = false; chip::ByteSpan credentials; - bool credentialsExists = false; uint64_t breadcrumb; - bool breadcrumbExists = false; uint32_t timeoutMs; - bool timeoutMsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (ssidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } - { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - ssid = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - ssidExists = true; - validArgumentCount++; - } - break; - case 1: - if (credentialsExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } + else { - const uint8_t * data = nullptr; - TLVUnpackError = aDataTlv.GetDataPtr(data); - credentials = chip::ByteSpan(data, aDataTlv.GetLength()); - } - if (CHIP_NO_ERROR == TLVUnpackError) - { - credentialsExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } - break; + } + switch (currentDecodeTagId) + { + case 0: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + ssid = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + credentials = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; case 2: - if (breadcrumbExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(breadcrumb); - if (CHIP_NO_ERROR == TLVUnpackError) - { - breadcrumbExists = true; - validArgumentCount++; - } break; case 3: - if (timeoutMsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timeoutMs); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timeoutMsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6180,24 +4354,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(ssid, credentials, breadcrumb, timeoutMs); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -6206,10 +4368,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -6218,6 +4390,15 @@ namespace OnOff { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -6225,18 +4406,21 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOffCallback(); + return; break; } case ZCL_ON_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterOnCallback(); + return; break; } case ZCL_TOGGLE_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfOnOffClusterToggleCallback(); + return; break; } default: { @@ -6244,10 +4428,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_ON_OFF_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 5, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace OnOff @@ -6256,114 +4450,76 @@ namespace Scenes { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 3: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 4: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6371,67 +4527,56 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterAddSceneCallback(groupId, sceneId, transitionTime, const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_SCENE_MEMBERSHIP_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6439,98 +4584,63 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterGetSceneMembershipCallback(groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_RECALL_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 2: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6538,66 +4648,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRecallSceneCallback(groupId, sceneId, transitionTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_ALL_SCENES_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6605,82 +4704,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveAllScenesCallback(groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6688,82 +4764,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveSceneCallback(groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STORE_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6771,82 +4824,59 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterStoreSceneCallback(groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_SCENE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (groupIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - groupIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(groupId); break; case 1: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -6854,24 +4884,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterViewSceneCallback(groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -6880,10 +4898,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 3, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes diff --git a/examples/window-app/common/gen/IMClusterCommandHandler.cpp b/examples/window-app/common/gen/IMClusterCommandHandler.cpp index c94cbd2bc8be59..8b12261ce31e2b 100644 --- a/examples/window-app/common/gen/IMClusterCommandHandler.cpp +++ b/examples/window-app/common/gen/IMClusterCommandHandler.cpp @@ -43,6 +43,15 @@ namespace WindowCovering { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { @@ -50,47 +59,49 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfWindowCoveringClusterWindowCoveringDownCloseCallback(); + return; break; } case ZCL_WINDOW_COVERING_GO_TO_LIFT_PERCENTAGE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t percentageLiftValue; - bool percentageLiftValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (percentageLiftValueExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(percentageLiftValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - percentageLiftValueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(percentageLiftValue); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -98,66 +109,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfWindowCoveringClusterWindowCoveringGoToLiftPercentageCallback(percentageLiftValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_WINDOW_COVERING_GO_TO_LIFT_VALUE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t liftValue; - bool liftValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (liftValueExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(liftValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - liftValueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(liftValue); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -165,66 +165,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfWindowCoveringClusterWindowCoveringGoToLiftValueCallback(liftValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_WINDOW_COVERING_GO_TO_TILT_PERCENTAGE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t percentageTiltValue; - bool percentageTiltValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (percentageTiltValueExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(percentageTiltValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - percentageTiltValueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(percentageTiltValue); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -232,66 +221,55 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfWindowCoveringClusterWindowCoveringGoToTiltPercentageCallback(percentageTiltValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_WINDOW_COVERING_GO_TO_TILT_VALUE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t tiltValue; - bool tiltValueExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (tiltValueExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(tiltValue); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - tiltValueExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(tiltValue); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -299,24 +277,12 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfWindowCoveringClusterWindowCoveringGoToTiltValueCallback(tiltValue); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -324,12 +290,14 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfWindowCoveringClusterWindowCoveringStopCallback(); + return; break; } case ZCL_WINDOW_COVERING_UP_OPEN_COMMAND_ID: { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfWindowCoveringClusterWindowCoveringUpOpenCallback(); + return; break; } default: { @@ -337,10 +305,20 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_WINDOW_COVERING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 5, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace WindowCovering diff --git a/src/controller/CHIPClusters.cpp b/src/controller/CHIPClusters.cpp index 5823480becce4c..a925159b2d6ebd 100644 --- a/src/controller/CHIPClusters.cpp +++ b/src/controller/CHIPClusters.cpp @@ -107,7 +107,6 @@ CHIP_ERROR ApplicationBasicCluster::ReadAttributeClusterRevision(Callback::Cance CHIP_ERROR BarrierControlCluster::BarrierControlGoToPercent(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t percentOpen) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -130,18 +129,11 @@ CHIP_ERROR BarrierControlCluster::BarrierControlGoToPercent(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBarrierControlClusterBarrierControlGoToPercentCommand(seqNum, mEndpoint, percentOpen); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR BarrierControlCluster::BarrierControlStop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -162,11 +154,6 @@ CHIP_ERROR BarrierControlCluster::BarrierControlStop(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeBarrierControlClusterBarrierControlStopCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // BarrierControl Cluster Attributes @@ -220,7 +207,6 @@ CHIP_ERROR BarrierControlCluster::ReadAttributeClusterRevision(Callback::Cancela // Basic Cluster Commands CHIP_ERROR BasicCluster::MfgSpecificPing(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -241,11 +227,6 @@ CHIP_ERROR BasicCluster::MfgSpecificPing(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeBasicClusterMfgSpecificPingCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Basic Cluster Attributes @@ -366,7 +347,6 @@ CHIP_ERROR BasicCluster::ReadAttributeClusterRevision(Callback::Cancelable * onS CHIP_ERROR BindingCluster::Bind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::NodeId nodeId, chip::GroupId groupId, chip::EndpointId endpointId, chip::ClusterId clusterId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -395,19 +375,12 @@ CHIP_ERROR BindingCluster::Bind(Callback::Cancelable * onSuccessCallback, Callba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBindingClusterBindCommand(seqNum, mEndpoint, nodeId, groupId, endpointId, clusterId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR BindingCluster::Unbind(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::NodeId nodeId, chip::GroupId groupId, chip::EndpointId endpointId, chip::ClusterId clusterId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -436,12 +409,6 @@ CHIP_ERROR BindingCluster::Unbind(Callback::Cancelable * onSuccessCallback, Call ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeBindingClusterUnbindCommand(seqNum, mEndpoint, nodeId, groupId, endpointId, clusterId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Binding Cluster Attributes @@ -463,7 +430,6 @@ CHIP_ERROR BindingCluster::ReadAttributeClusterRevision(Callback::Cancelable * o CHIP_ERROR ColorControlCluster::MoveColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, int16_t rateX, int16_t rateY, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -492,12 +458,6 @@ CHIP_ERROR ColorControlCluster::MoveColor(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveColorCommand(seqNum, mEndpoint, rateX, rateY, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSuccessCallback, @@ -505,7 +465,6 @@ CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSu uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -538,18 +497,11 @@ CHIP_ERROR ColorControlCluster::MoveColorTemperature(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveColorTemperatureCommand( - seqNum, mEndpoint, moveMode, rate, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -578,18 +530,11 @@ CHIP_ERROR ColorControlCluster::MoveHue(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveHueCommand(seqNum, mEndpoint, moveMode, rate, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -618,19 +563,12 @@ CHIP_ERROR ColorControlCluster::MoveSaturation(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveSaturationCommand(seqNum, mEndpoint, moveMode, rate, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t colorX, uint16_t colorY, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -661,19 +599,12 @@ CHIP_ERROR ColorControlCluster::MoveToColor(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToColorCommand( - seqNum, mEndpoint, colorX, colorY, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToColorTemperature(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t colorTemperature, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -702,19 +633,12 @@ CHIP_ERROR ColorControlCluster::MoveToColorTemperature(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToColorTemperatureCommand( - seqNum, mEndpoint, colorTemperature, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t hue, uint8_t direction, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -745,19 +669,12 @@ CHIP_ERROR ColorControlCluster::MoveToHue(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterMoveToHueCommand(seqNum, mEndpoint, hue, direction, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToHueAndSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t hue, uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -788,19 +705,12 @@ CHIP_ERROR ColorControlCluster::MoveToHueAndSaturation(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToHueAndSaturationCommand( - seqNum, mEndpoint, hue, saturation, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::MoveToSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -829,19 +739,12 @@ CHIP_ERROR ColorControlCluster::MoveToSaturation(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterMoveToSaturationCommand( - seqNum, mEndpoint, saturation, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepColor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, int16_t stepX, int16_t stepY, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -872,12 +775,6 @@ CHIP_ERROR ColorControlCluster::StepColor(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterStepColorCommand(seqNum, mEndpoint, stepX, stepY, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSuccessCallback, @@ -885,7 +782,6 @@ CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSu uint16_t transitionTime, uint16_t colorTemperatureMinimum, uint16_t colorTemperatureMaximum, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -920,20 +816,12 @@ CHIP_ERROR ColorControlCluster::StepColorTemperature(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepColorTemperatureCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, colorTemperatureMinimum, colorTemperatureMaximum, optionsMask, - optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepHue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -964,19 +852,12 @@ CHIP_ERROR ColorControlCluster::StepHue(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepHueCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StepSaturation(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint8_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1007,18 +888,11 @@ CHIP_ERROR ColorControlCluster::StepSaturation(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeColorControlClusterStepSaturationCommand( - seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ColorControlCluster::StopMoveStep(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t optionsMask, uint8_t optionsOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1043,12 +917,6 @@ CHIP_ERROR ColorControlCluster::StopMoveStep(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeColorControlClusterStopMoveStepCommand(seqNum, mEndpoint, optionsMask, optionsOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // ColorControl Cluster Attributes @@ -1705,7 +1573,6 @@ CHIP_ERROR DescriptorCluster::ReadAttributeClusterRevision(Callback::Cancelable // DoorLock Cluster Commands CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1726,16 +1593,10 @@ CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearAllPinsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearAllRfids(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1756,17 +1617,11 @@ CHIP_ERROR DoorLockCluster::ClearAllRfids(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearAllRfidsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1789,17 +1644,11 @@ CHIP_ERROR DoorLockCluster::ClearHolidaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearHolidayScheduleCommand(seqNum, mEndpoint, scheduleId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1822,17 +1671,11 @@ CHIP_ERROR DoorLockCluster::ClearPin(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearPinCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1855,17 +1698,11 @@ CHIP_ERROR DoorLockCluster::ClearRfid(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterClearRfidCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1890,18 +1727,11 @@ CHIP_ERROR DoorLockCluster::ClearWeekdaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterClearWeekdayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::ClearYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1926,18 +1756,11 @@ CHIP_ERROR DoorLockCluster::ClearYeardaySchedule(Callback::Cancelable * onSucces ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterClearYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1960,17 +1783,11 @@ CHIP_ERROR DoorLockCluster::GetHolidaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetHolidayScheduleCommand(seqNum, mEndpoint, scheduleId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetLogRecord(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t logIndex) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -1993,17 +1810,11 @@ CHIP_ERROR DoorLockCluster::GetLogRecord(Callback::Cancelable * onSuccessCallbac ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetLogRecordCommand(seqNum, mEndpoint, logIndex); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2026,17 +1837,11 @@ CHIP_ERROR DoorLockCluster::GetPin(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetPinCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2059,17 +1864,11 @@ CHIP_ERROR DoorLockCluster::GetRfid(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetRfidCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetUserType(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2092,17 +1891,11 @@ CHIP_ERROR DoorLockCluster::GetUserType(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterGetUserTypeCommand(seqNum, mEndpoint, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2127,18 +1920,11 @@ CHIP_ERROR DoorLockCluster::GetWeekdaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterGetWeekdayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::GetYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2163,18 +1949,11 @@ CHIP_ERROR DoorLockCluster::GetYeardaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterGetYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::LockDoor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2197,18 +1976,12 @@ CHIP_ERROR DoorLockCluster::LockDoor(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterLockDoorCommand(seqNum, mEndpoint, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetHolidaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint32_t localStartTime, uint32_t localEndTime, uint8_t operatingModeDuringHoliday) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2237,18 +2010,11 @@ CHIP_ERROR DoorLockCluster::SetHolidaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetHolidayScheduleCommand( - seqNum, mEndpoint, scheduleId, localStartTime, localEndTime, operatingModeDuringHoliday); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetPin(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userStatus, uint8_t userType, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2277,18 +2043,11 @@ CHIP_ERROR DoorLockCluster::SetPin(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetPinCommand(seqNum, mEndpoint, userId, userStatus, userType, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetRfid(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userStatus, uint8_t userType, chip::ByteSpan id) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2317,18 +2076,11 @@ CHIP_ERROR DoorLockCluster::SetRfid(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetRfidCommand(seqNum, mEndpoint, userId, userStatus, userType, id); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetUserType(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t userId, uint8_t userType) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2353,18 +2105,12 @@ CHIP_ERROR DoorLockCluster::SetUserType(Callback::Cancelable * onSuccessCallback ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetUserTypeCommand(seqNum, mEndpoint, userId, userType); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetWeekdaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId, uint8_t daysMask, uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2399,18 +2145,11 @@ CHIP_ERROR DoorLockCluster::SetWeekdaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterSetWeekdayScheduleCommand( - seqNum, mEndpoint, scheduleId, userId, daysMask, startHour, startMinute, endHour, endMinute); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::SetYeardaySchedule(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t scheduleId, uint16_t userId, uint32_t localStartTime, uint32_t localEndTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2439,18 +2178,11 @@ CHIP_ERROR DoorLockCluster::SetYeardaySchedule(Callback::Cancelable * onSuccessC ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterSetYeardayScheduleCommand(seqNum, mEndpoint, scheduleId, userId, localStartTime, localEndTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::UnlockDoor(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2473,17 +2205,11 @@ CHIP_ERROR DoorLockCluster::UnlockDoor(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeDoorLockClusterUnlockDoorCommand(seqNum, mEndpoint, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR DoorLockCluster::UnlockWithTimeout(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t timeoutInSeconds, chip::ByteSpan pin) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2508,12 +2234,6 @@ CHIP_ERROR DoorLockCluster::UnlockWithTimeout(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeDoorLockClusterUnlockWithTimeoutCommand(seqNum, mEndpoint, timeoutInSeconds, pin); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // DoorLock Cluster Attributes @@ -2575,7 +2295,6 @@ CHIP_ERROR GeneralCommissioningCluster::ArmFailSafe(Callback::Cancelable * onSuc Callback::Cancelable * onFailureCallback, uint16_t expiryLengthSeconds, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2602,18 +2321,11 @@ CHIP_ERROR GeneralCommissioningCluster::ArmFailSafe(Callback::Cancelable * onSuc ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGeneralCommissioningClusterArmFailSafeCommand(seqNum, mEndpoint, expiryLengthSeconds, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GeneralCommissioningCluster::CommissioningComplete(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2634,18 +2346,12 @@ CHIP_ERROR GeneralCommissioningCluster::CommissioningComplete(Callback::Cancelab ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGeneralCommissioningClusterCommissioningCompleteCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GeneralCommissioningCluster::SetFabric(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan fabricId, chip::ByteSpan fabricSecret, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2674,12 +2380,6 @@ CHIP_ERROR GeneralCommissioningCluster::SetFabric(Callback::Cancelable * onSucce ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGeneralCommissioningClusterSetFabricCommand(seqNum, mEndpoint, fabricId, fabricSecret, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // GeneralCommissioning Cluster Attributes @@ -2759,7 +2459,6 @@ CHIP_ERROR GroupKeyManagementCluster::ReadAttributeClusterRevision(Callback::Can CHIP_ERROR GroupsCluster::AddGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, chip::ByteSpan groupName) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2784,17 +2483,11 @@ CHIP_ERROR GroupsCluster::AddGroup(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterAddGroupCommand(seqNum, mEndpoint, groupId, groupName); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, chip::ByteSpan groupName) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2819,18 +2512,11 @@ CHIP_ERROR GroupsCluster::AddGroupIfIdentifying(Callback::Cancelable * onSuccess ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGroupsClusterAddGroupIfIdentifyingCommand(seqNum, mEndpoint, groupId, groupName); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::GetGroupMembership(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t groupCount, uint16_t groupList) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2855,17 +2541,10 @@ CHIP_ERROR GroupsCluster::GetGroupMembership(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeGroupsClusterGetGroupMembershipCommand(seqNum, mEndpoint, groupCount, groupList); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::RemoveAllGroups(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2886,17 +2565,11 @@ CHIP_ERROR GroupsCluster::RemoveAllGroups(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterRemoveAllGroupsCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::RemoveGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2919,17 +2592,11 @@ CHIP_ERROR GroupsCluster::RemoveGroup(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterRemoveGroupCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR GroupsCluster::ViewGroup(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -2952,11 +2619,6 @@ CHIP_ERROR GroupsCluster::ViewGroup(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeGroupsClusterViewGroupCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Groups Cluster Attributes @@ -3048,7 +2710,6 @@ CHIP_ERROR IasZoneCluster::ReadAttributeClusterRevision(Callback::Cancelable * o CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t identifyTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3071,16 +2732,10 @@ CHIP_ERROR IdentifyCluster::Identify(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyCommand(seqNum, mEndpoint, identifyTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3101,11 +2756,6 @@ CHIP_ERROR IdentifyCluster::IdentifyQuery(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeIdentifyClusterIdentifyQueryCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Identify Cluster Attributes @@ -3143,7 +2793,6 @@ CHIP_ERROR IdentifyCluster::ReadAttributeClusterRevision(Callback::Cancelable * CHIP_ERROR LevelControlCluster::Move(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3172,18 +2821,11 @@ CHIP_ERROR LevelControlCluster::Move(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveCommand(seqNum, mEndpoint, moveMode, rate, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveToLevel(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t level, uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3212,19 +2854,12 @@ CHIP_ERROR LevelControlCluster::MoveToLevel(Callback::Cancelable * onSuccessCall ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveToLevelCommand(seqNum, mEndpoint, level, transitionTime, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveToLevelWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t level, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3249,18 +2884,11 @@ CHIP_ERROR LevelControlCluster::MoveToLevelWithOnOff(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterMoveToLevelWithOnOffCommand(seqNum, mEndpoint, level, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::MoveWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t moveMode, uint8_t rate) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3285,18 +2913,12 @@ CHIP_ERROR LevelControlCluster::MoveWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterMoveWithOnOffCommand(seqNum, mEndpoint, moveMode, rate); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::Step(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3327,18 +2949,11 @@ CHIP_ERROR LevelControlCluster::Step(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterStepCommand(seqNum, mEndpoint, stepMode, stepSize, transitionTime, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::StepWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t stepMode, uint8_t stepSize, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3365,18 +2980,11 @@ CHIP_ERROR LevelControlCluster::StepWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeLevelControlClusterStepWithOnOffCommand(seqNum, mEndpoint, stepMode, stepSize, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::Stop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t optionMask, uint8_t optionOverride) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3401,16 +3009,10 @@ CHIP_ERROR LevelControlCluster::Stop(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterStopCommand(seqNum, mEndpoint, optionMask, optionOverride); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR LevelControlCluster::StopWithOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3431,11 +3033,6 @@ CHIP_ERROR LevelControlCluster::StopWithOnOff(Callback::Cancelable * onSuccessCa ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLevelControlClusterStopWithOnOffCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // LevelControl Cluster Attributes @@ -3480,7 +3077,6 @@ CHIP_ERROR LevelControlCluster::ReadAttributeClusterRevision(Callback::Cancelabl // LowPower Cluster Commands CHIP_ERROR LowPowerCluster::Sleep(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3501,11 +3097,6 @@ CHIP_ERROR LowPowerCluster::Sleep(Callback::Cancelable * onSuccessCallback, Call ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeLowPowerClusterSleepCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // LowPower Cluster Attributes @@ -3528,7 +3119,6 @@ CHIP_ERROR NetworkCommissioningCluster::AddThreadNetwork(Callback::Cancelable * Callback::Cancelable * onFailureCallback, chip::ByteSpan operationalDataset, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3555,19 +3145,12 @@ CHIP_ERROR NetworkCommissioningCluster::AddThreadNetwork(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterAddThreadNetworkCommand(seqNum, mEndpoint, operationalDataset, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::AddWiFiNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, chip::ByteSpan credentials, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3596,19 +3179,12 @@ CHIP_ERROR NetworkCommissioningCluster::AddWiFiNetwork(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterAddWiFiNetworkCommand(seqNum, mEndpoint, ssid, credentials, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::DisableNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3635,19 +3211,12 @@ CHIP_ERROR NetworkCommissioningCluster::DisableNetwork(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterDisableNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::EnableNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3674,19 +3243,12 @@ CHIP_ERROR NetworkCommissioningCluster::EnableNetwork(Callback::Cancelable * onS ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterEnableNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::GetLastNetworkCommissioningResult(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3709,19 +3271,12 @@ CHIP_ERROR NetworkCommissioningCluster::GetLastNetworkCommissioningResult(Callba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterGetLastNetworkCommissioningResultCommand(seqNum, mEndpoint, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::RemoveNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan networkID, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3748,19 +3303,12 @@ CHIP_ERROR NetworkCommissioningCluster::RemoveNetwork(Callback::Cancelable * onS ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterRemoveNetworkCommand(seqNum, mEndpoint, networkID, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::ScanNetworks(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3787,12 +3335,6 @@ CHIP_ERROR NetworkCommissioningCluster::ScanNetworks(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterScanNetworksCommand(seqNum, mEndpoint, ssid, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable * onSuccessCallback, @@ -3800,7 +3342,6 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable chip::ByteSpan operationalDataset, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3827,19 +3368,12 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateThreadNetwork(Callback::Cancelable ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterUpdateThreadNetworkCommand(seqNum, mEndpoint, operationalDataset, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR NetworkCommissioningCluster::UpdateWiFiNetwork(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, chip::ByteSpan ssid, chip::ByteSpan credentials, uint64_t breadcrumb, uint32_t timeoutMs) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3868,12 +3402,6 @@ CHIP_ERROR NetworkCommissioningCluster::UpdateWiFiNetwork(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeNetworkCommissioningClusterUpdateWiFiNetworkCommand(seqNum, mEndpoint, ssid, credentials, breadcrumb, timeoutMs); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // NetworkCommissioning Cluster Attributes @@ -3895,7 +3423,6 @@ CHIP_ERROR NetworkCommissioningCluster::ReadAttributeClusterRevision(Callback::C // OnOff Cluster Commands CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3916,16 +3443,10 @@ CHIP_ERROR OnOffCluster::Off(Callback::Cancelable * onSuccessCallback, Callback: ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOffCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3946,16 +3467,10 @@ CHIP_ERROR OnOffCluster::On(Callback::Cancelable * onSuccessCallback, Callback:: ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterOnCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -3976,11 +3491,6 @@ CHIP_ERROR OnOffCluster::Toggle(Callback::Cancelable * onSuccessCallback, Callba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeOnOffClusterToggleCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // OnOff Cluster Attributes @@ -4024,7 +3534,6 @@ CHIP_ERROR ScenesCluster::AddScene(Callback::Cancelable * onSuccessCallback, Cal uint16_t groupId, uint8_t sceneId, uint16_t transitionTime, chip::ByteSpan sceneName, chip::ClusterId clusterId, uint8_t length, uint8_t value) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4059,18 +3568,11 @@ CHIP_ERROR ScenesCluster::AddScene(Callback::Cancelable * onSuccessCallback, Cal ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterAddSceneCommand( - seqNum, mEndpoint, groupId, sceneId, transitionTime, sceneName, clusterId, length, value); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::GetSceneMembership(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4093,17 +3595,11 @@ CHIP_ERROR ScenesCluster::GetSceneMembership(Callback::Cancelable * onSuccessCal ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterGetSceneMembershipCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RecallScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId, uint16_t transitionTime) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4130,18 +3626,11 @@ CHIP_ERROR ScenesCluster::RecallScene(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeScenesClusterRecallSceneCommand(seqNum, mEndpoint, groupId, sceneId, transitionTime); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RemoveAllScenes(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4164,17 +3653,11 @@ CHIP_ERROR ScenesCluster::RemoveAllScenes(Callback::Cancelable * onSuccessCallba ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterRemoveAllScenesCommand(seqNum, mEndpoint, groupId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::RemoveScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4199,17 +3682,11 @@ CHIP_ERROR ScenesCluster::RemoveScene(Callback::Cancelable * onSuccessCallback, ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterRemoveSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::StoreScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4234,17 +3711,11 @@ CHIP_ERROR ScenesCluster::StoreScene(Callback::Cancelable * onSuccessCallback, C ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterStoreSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR ScenesCluster::ViewScene(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t groupId, uint8_t sceneId) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4269,11 +3740,6 @@ CHIP_ERROR ScenesCluster::ViewScene(Callback::Cancelable * onSuccessCallback, Ca ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeScenesClusterViewSceneCommand(seqNum, mEndpoint, groupId, sceneId); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // Scenes Cluster Attributes @@ -4392,7 +3858,6 @@ CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeClusterRevision(Callback: CHIP_ERROR WindowCoveringCluster::WindowCoveringDownClose(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4413,18 +3878,12 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringDownClose(Callback::Cancelable * ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeWindowCoveringClusterWindowCoveringDownCloseCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToLiftPercentage(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t percentageLiftValue) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4447,18 +3906,11 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToLiftPercentage(Callback::Can ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeWindowCoveringClusterWindowCoveringGoToLiftPercentageCommand(seqNum, mEndpoint, percentageLiftValue); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToLiftValue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t liftValue) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4481,19 +3933,12 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToLiftValue(Callback::Cancelab ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeWindowCoveringClusterWindowCoveringGoToLiftValueCommand(seqNum, mEndpoint, liftValue); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToTiltPercentage(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t percentageTiltValue) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4516,18 +3961,11 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToTiltPercentage(Callback::Can ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeWindowCoveringClusterWindowCoveringGoToTiltPercentageCommand(seqNum, mEndpoint, percentageTiltValue); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToTiltValue(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t tiltValue) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4550,18 +3988,11 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringGoToTiltValue(Callback::Cancelab ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = - encodeWindowCoveringClusterWindowCoveringGoToTiltValueCommand(seqNum, mEndpoint, tiltValue); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringStop(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4582,17 +4013,11 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringStop(Callback::Cancelable * onSu ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeWindowCoveringClusterWindowCoveringStopCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } CHIP_ERROR WindowCoveringCluster::WindowCoveringUpOpen(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { -#if CHIP_ENABLE_INTERACTION_MODEL VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); (void) onSuccessCallback; (void) onFailureCallback; @@ -4613,11 +4038,6 @@ CHIP_ERROR WindowCoveringCluster::WindowCoveringUpOpen(Callback::Cancelable * on ReturnErrorOnFailure(ZCLcommand->AddCommand(cmdParams)); return mDevice->SendCommands(); -#else - uint8_t seqNum = mDevice->GetNextSequenceNumber(); - System::PacketBufferHandle encodedCommand = encodeWindowCoveringClusterWindowCoveringUpOpenCommand(seqNum, mEndpoint); - return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); -#endif } // WindowCovering Cluster Attributes diff --git a/src/controller/python/gen/IMClusterCommandHandler.cpp b/src/controller/python/gen/IMClusterCommandHandler.cpp index 574aeb84b0d42f..df5a20c0436551 100644 --- a/src/controller/python/gen/IMClusterCommandHandler.cpp +++ b/src/controller/python/gen/IMClusterCommandHandler.cpp @@ -43,48 +43,58 @@ namespace DoorLock { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_CLEAR_ALL_PINS_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -92,66 +102,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllPinsResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -159,66 +158,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllRfidsResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -226,66 +214,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearHolidayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -293,66 +270,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearPinResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -360,66 +326,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearRfidResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -427,66 +382,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -494,130 +438,71 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearYeardayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; uint8_t operatingModeDuringHoliday; - bool operatingModeDuringHolidayExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 2: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 3: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; case 4: - if (operatingModeDuringHolidayExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - if (CHIP_NO_ERROR == TLVUnpackError) - { - operatingModeDuringHolidayExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -625,164 +510,81 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetHolidayScheduleResponseCallback(scheduleId, status, localStartTime, localEndTime, operatingModeDuringHoliday); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint16_t logEntryId; - bool logEntryIdExists = false; uint32_t timestamp; - bool timestampExists = false; uint8_t eventType; - bool eventTypeExists = false; uint8_t source; - bool sourceExists = false; uint8_t eventIdOrAlarmCode; - bool eventIdOrAlarmCodeExists = false; uint16_t userId; - bool userIdExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (logEntryIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 7) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(logEntryId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - logEntryIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(logEntryId); break; case 1: - if (timestampExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timestamp); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timestampExists = true; - validArgumentCount++; - } break; case 2: - if (eventTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventTypeExists = true; - validArgumentCount++; - } break; case 3: - if (sourceExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(source); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sourceExists = true; - validArgumentCount++; - } break; case 4: - if (eventIdOrAlarmCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventIdOrAlarmCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventIdOrAlarmCodeExists = true; - validArgumentCount++; - } break; case 5: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 6: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -790,116 +592,69 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetLogRecordResponseCallback(logEntryId, timestamp, eventType, source, eventIdOrAlarmCode, userId, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_PIN_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -907,115 +662,68 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetPinResponseCallback(userId, userStatus, userType, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_RFID_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * rfid; - bool rfidExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (rfidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(rfid); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rfidExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1023,82 +731,59 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetRfidResponseCallback(userId, userStatus, userType, const_cast(rfid)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t userId; - bool userIdExists = false; uint8_t userType; - bool userTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1106,178 +791,83 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetUserTypeResponseCallback(userId, userType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 8; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint8_t daysMask; - bool daysMaskExists = false; uint8_t startHour; - bool startHourExists = false; uint8_t startMinute; - bool startMinuteExists = false; uint8_t endHour; - bool endHourExists = false; uint8_t endMinute; - bool endMinuteExists = false; - uint32_t validArgumentCount = 0; + bool argExists[8]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 8) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (daysMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(daysMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - daysMaskExists = true; - validArgumentCount++; - } break; case 4: - if (startHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startHourExists = true; - validArgumentCount++; - } break; case 5: - if (startMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startMinuteExists = true; - validArgumentCount++; - } break; case 6: - if (endHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endHourExists = true; - validArgumentCount++; - } break; case 7: - if (endMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endMinuteExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1285,131 +875,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 8 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(scheduleId, userId, status, daysMask, startHour, startMinute, endHour, endMinute); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 8, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 4: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1417,66 +948,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetYeardayScheduleResponseCallback(scheduleId, userId, status, localStartTime, localEndTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1484,66 +1004,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterLockDoorResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1551,66 +1060,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetHolidayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_PIN_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1618,66 +1116,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetPinResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_RFID_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1685,66 +1172,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetRfidResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1752,66 +1228,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetUserTypeResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1819,66 +1284,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1886,66 +1340,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetYeardayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1953,66 +1396,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockDoorResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2020,24 +1452,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2046,10 +1466,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -2058,65 +1488,63 @@ namespace GeneralCommissioning { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2124,83 +1552,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_COMMISSIONING_COMPLETE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2208,84 +1613,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_FABRIC_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2293,24 +1675,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterSetFabricResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2319,10 +1689,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -2331,64 +1711,62 @@ namespace Groups { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_GROUP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2396,99 +1774,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterAddGroupResponseCallback(status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t capacity; - bool capacityExists = false; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (capacityExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - capacityExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(capacity); break; case 1: - if (groupCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupCountExists = true; - validArgumentCount++; - } break; case 2: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2496,82 +1839,59 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterGetGroupMembershipResponseCallback(capacity, groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2579,99 +1899,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterRemoveGroupResponseCallback(status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2679,24 +1964,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterViewGroupResponseCallback(status, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2705,10 +1978,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -2717,48 +2000,58 @@ namespace Identify { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_IDENTIFY_QUERY_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t timeout; - bool timeoutExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeout); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeout); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2766,24 +2059,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfIdentifyClusterIdentifyQueryResponseCallback(timeout); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2792,10 +2073,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -2804,80 +2095,66 @@ namespace Scenes { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2885,131 +2162,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterAddSceneResponseCallback(status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t status; - bool statusExists = false; uint8_t capacity; - bool capacityExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneCount; - bool sceneCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * sceneList; - bool sceneListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (capacityExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) - { - capacityExists = true; - validArgumentCount++; - } break; case 2: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 3: - if (sceneCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneCountExists = true; - validArgumentCount++; - } break; case 4: - if (sceneListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(sceneList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3017,82 +2235,59 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterGetSceneMembershipResponseCallback(status, capacity, groupId, sceneCount, sceneList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3100,98 +2295,63 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveAllScenesResponseCallback(status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3199,98 +2359,63 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveSceneResponseCallback(status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STORE_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3298,148 +2423,77 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterStoreSceneResponseCallback(status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 3: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 4: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 5: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3447,25 +2501,13 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterViewSceneResponseCallback(status, groupId, sceneId, transitionTime, const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -3474,10 +2516,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes diff --git a/src/darwin/Framework/CHIP/gen/IMClusterCommandHandler.cpp b/src/darwin/Framework/CHIP/gen/IMClusterCommandHandler.cpp index 96a8be3f1c5de1..230f5e4f80cd21 100644 --- a/src/darwin/Framework/CHIP/gen/IMClusterCommandHandler.cpp +++ b/src/darwin/Framework/CHIP/gen/IMClusterCommandHandler.cpp @@ -43,48 +43,58 @@ namespace DoorLock { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_CLEAR_ALL_PINS_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -92,66 +102,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllPinsResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -159,66 +158,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearAllRfidsResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -226,66 +214,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearHolidayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_PIN_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -293,66 +270,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearPinResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_RFID_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -360,66 +326,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearRfidResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -427,66 +382,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -494,130 +438,71 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterClearYeardayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; uint8_t operatingModeDuringHoliday; - bool operatingModeDuringHolidayExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 2: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 3: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; case 4: - if (operatingModeDuringHolidayExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday); - if (CHIP_NO_ERROR == TLVUnpackError) - { - operatingModeDuringHolidayExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -625,164 +510,81 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetHolidayScheduleResponseCallback(scheduleId, status, localStartTime, localEndTime, operatingModeDuringHoliday); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 7; uint16_t logEntryId; - bool logEntryIdExists = false; uint32_t timestamp; - bool timestampExists = false; uint8_t eventType; - bool eventTypeExists = false; uint8_t source; - bool sourceExists = false; uint8_t eventIdOrAlarmCode; - bool eventIdOrAlarmCodeExists = false; uint16_t userId; - bool userIdExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[7]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (logEntryIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 7) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(logEntryId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - logEntryIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(logEntryId); break; case 1: - if (timestampExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(timestamp); - if (CHIP_NO_ERROR == TLVUnpackError) - { - timestampExists = true; - validArgumentCount++; - } break; case 2: - if (eventTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventTypeExists = true; - validArgumentCount++; - } break; case 3: - if (sourceExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(source); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sourceExists = true; - validArgumentCount++; - } break; case 4: - if (eventIdOrAlarmCodeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(eventIdOrAlarmCode); - if (CHIP_NO_ERROR == TLVUnpackError) - { - eventIdOrAlarmCodeExists = true; - validArgumentCount++; - } break; case 5: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 6: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -790,116 +592,69 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetLogRecordResponseCallback(logEntryId, timestamp, eventType, source, eventIdOrAlarmCode, userId, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 7, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_PIN_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * pin; - bool pinExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (pinExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(pin); - if (CHIP_NO_ERROR == TLVUnpackError) - { - pinExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -907,115 +662,68 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetPinResponseCallback(userId, userStatus, userType, const_cast(pin)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_RFID_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint16_t userId; - bool userIdExists = false; uint8_t userStatus; - bool userStatusExists = false; uint8_t userType; - bool userTypeExists = false; const uint8_t * rfid; - bool rfidExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userStatusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userStatus); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userStatusExists = true; - validArgumentCount++; - } break; case 2: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; case 3: - if (rfidExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(rfid); - if (CHIP_NO_ERROR == TLVUnpackError) - { - rfidExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1023,82 +731,59 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetRfidResponseCallback(userId, userStatus, userType, const_cast(rfid)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint16_t userId; - bool userIdExists = false; uint8_t userType; - bool userTypeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (userIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - userIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(userId); break; case 1: - if (userTypeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userType); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userTypeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1106,178 +791,83 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetUserTypeResponseCallback(userId, userType); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 8; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint8_t daysMask; - bool daysMaskExists = false; uint8_t startHour; - bool startHourExists = false; uint8_t startMinute; - bool startMinuteExists = false; uint8_t endHour; - bool endHourExists = false; uint8_t endMinute; - bool endMinuteExists = false; - uint32_t validArgumentCount = 0; + bool argExists[8]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 8) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (daysMaskExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(daysMask); - if (CHIP_NO_ERROR == TLVUnpackError) - { - daysMaskExists = true; - validArgumentCount++; - } break; case 4: - if (startHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startHourExists = true; - validArgumentCount++; - } break; case 5: - if (startMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(startMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - startMinuteExists = true; - validArgumentCount++; - } break; case 6: - if (endHourExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endHour); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endHourExists = true; - validArgumentCount++; - } break; case 7: - if (endMinuteExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(endMinute); - if (CHIP_NO_ERROR == TLVUnpackError) - { - endMinuteExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1285,131 +875,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 8 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(scheduleId, userId, status, daysMask, startHour, startMinute, endHour, endMinute); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 8, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t scheduleId; - bool scheduleIdExists = false; uint16_t userId; - bool userIdExists = false; uint8_t status; - bool statusExists = false; uint32_t localStartTime; - bool localStartTimeExists = false; uint32_t localEndTime; - bool localEndTimeExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (scheduleIdExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(scheduleId); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - scheduleIdExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(scheduleId); break; case 1: - if (userIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(userId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - userIdExists = true; - validArgumentCount++; - } break; case 2: - if (statusExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) - { - statusExists = true; - validArgumentCount++; - } break; case 3: - if (localStartTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localStartTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localStartTimeExists = true; - validArgumentCount++; - } break; case 4: - if (localEndTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(localEndTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - localEndTimeExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1417,66 +948,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterGetYeardayScheduleResponseCallback(scheduleId, userId, status, localStartTime, localEndTime); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_LOCK_DOOR_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1484,66 +1004,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterLockDoorResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1551,66 +1060,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetHolidayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_PIN_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1618,66 +1116,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetPinResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_RFID_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1685,66 +1172,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetRfidResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_USER_TYPE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1752,66 +1228,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetUserTypeResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1819,66 +1284,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1886,66 +1340,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterSetYeardayScheduleResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -1953,66 +1396,55 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockDoorResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint8_t status; - bool statusExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2020,24 +1452,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(status); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2046,10 +1466,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 0, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace DoorLock @@ -2058,65 +1488,63 @@ namespace GeneralCommissioning { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ARM_FAIL_SAFE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2124,83 +1552,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_COMMISSIONING_COMPLETE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2208,84 +1613,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SET_FABRIC_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2293,24 +1675,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGeneralCommissioningClusterSetFabricResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2319,10 +1689,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace GeneralCommissioning @@ -2331,64 +1711,62 @@ namespace Groups { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_GROUP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2396,99 +1774,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterAddGroupResponseCallback(status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t capacity; - bool capacityExists = false; uint8_t groupCount; - bool groupCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * groupList; - bool groupListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (capacityExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - capacityExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(capacity); break; case 1: - if (groupCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupCountExists = true; - validArgumentCount++; - } break; case 2: - if (groupListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(groupList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2496,82 +1839,59 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterGetGroupMembershipResponseCallback(capacity, groupCount, groupList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_GROUP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2579,99 +1899,64 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterRemoveGroupResponseCallback(status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; const uint8_t * groupName; - bool groupNameExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (groupNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(groupName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupNameExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2679,24 +1964,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfGroupsClusterViewGroupResponseCallback(status, groupId, const_cast(groupName)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2705,10 +1978,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_GROUPS_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Groups @@ -2717,48 +2000,58 @@ namespace Identify { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_IDENTIFY_QUERY_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 1; uint16_t timeout; - bool timeoutExists = false; - uint32_t validArgumentCount = 0; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (timeoutExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(timeout); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - timeoutExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(timeout); break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2766,24 +2059,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfIdentifyClusterIdentifyQueryResponseCallback(timeout); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 1, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -2792,10 +2073,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_IDENTIFY_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 1, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Identify @@ -2804,65 +2095,63 @@ namespace NetworkCommissioning { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_THREAD_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2870,83 +2159,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ADD_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -2954,83 +2220,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3038,83 +2281,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_ENABLE_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3122,83 +2342,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3206,117 +2403,70 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_SCAN_NETWORKS_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 4; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * wifiScanResults; - bool wifiScanResultsExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * threadScanResults; - bool threadScanResultsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[4]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 4) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; case 2: - if (wifiScanResultsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(wifiScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - wifiScanResultsExists = true; - validArgumentCount++; - } break; case 3: - if (threadScanResultsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(threadScanResults)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - threadScanResultsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3324,84 +2474,61 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterScanNetworksResponseCallback(errorCode, const_cast(debugText), wifiScanResults, threadScanResults); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 4, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_THREAD_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3409,83 +2536,60 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_UPDATE_WI_FI_NETWORK_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t errorCode; - bool errorCodeExists = false; const uint8_t * debugText; - bool debugTextExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (errorCodeExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(errorCode); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - errorCodeExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(errorCode); break; case 1: - if (debugTextExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(debugText); - if (CHIP_NO_ERROR == TLVUnpackError) - { - debugTextExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3493,24 +2597,12 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(errorCode, const_cast(debugText)); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -3519,10 +2611,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 2, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace NetworkCommissioning @@ -3531,80 +2633,66 @@ namespace Scenes { void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) { + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; { switch (aCommandId) { case ZCL_ADD_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3612,131 +2700,72 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterAddSceneResponseCallback(status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 5; uint8_t status; - bool statusExists = false; uint8_t capacity; - bool capacityExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneCount; - bool sceneCountExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * sceneList; - bool sceneListExists = false; - uint32_t validArgumentCount = 0; + bool argExists[5]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 5) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (capacityExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(capacity); - if (CHIP_NO_ERROR == TLVUnpackError) - { - capacityExists = true; - validArgumentCount++; - } break; case 2: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 3: - if (sceneCountExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneCount); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneCountExists = true; - validArgumentCount++; - } break; case 4: - if (sceneListExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(sceneList)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneListExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3744,82 +2773,59 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterGetSceneMembershipResponseCallback(status, capacity, groupId, sceneCount, sceneList); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 5, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 2; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[2]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 2) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3827,98 +2833,63 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveAllScenesResponseCallback(status, groupId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 2, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_REMOVE_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -3926,98 +2897,63 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterRemoveSceneResponseCallback(status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_STORE_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 3; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; - uint32_t validArgumentCount = 0; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4025,148 +2961,77 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterStoreSceneResponseCallback(status, groupId, sceneId); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 3, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } case ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID: { - // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV - // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. - // Any error value TLVUnpackError means we have received an illegal value. - CHIP_ERROR TLVError = CHIP_NO_ERROR; - CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + expectArgumentCount = 6; uint8_t status; - bool statusExists = false; uint16_t groupId; - bool groupIdExists = false; uint8_t sceneId; - bool sceneIdExists = false; uint16_t transitionTime; - bool transitionTimeExists = false; const uint8_t * sceneName; - bool sceneNameExists = false; /* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets; - bool extensionFieldSetsExists = false; - uint32_t validArgumentCount = 0; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) { - switch (TLV::TagNumFromTag(aDataTlv.GetTag())) + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) { - case 0: - if (statusExists) + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) { ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; break; } - TLVUnpackError = aDataTlv.Get(status); - if (CHIP_NO_ERROR == TLVUnpackError) + else { - statusExists = true; + argExists[currentDecodeTagId] = true; validArgumentCount++; } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(status); break; case 1: - if (groupIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(groupId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - groupIdExists = true; - validArgumentCount++; - } break; case 2: - if (sceneIdExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(sceneId); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneIdExists = true; - validArgumentCount++; - } break; case 3: - if (transitionTimeExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } TLVUnpackError = aDataTlv.Get(transitionTime); - if (CHIP_NO_ERROR == TLVUnpackError) - { - transitionTimeExists = true; - validArgumentCount++; - } break; case 4: - if (sceneNameExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types. TLVUnpackError = aDataTlv.GetDataPtr(sceneName); - if (CHIP_NO_ERROR == TLVUnpackError) - { - sceneNameExists = true; - validArgumentCount++; - } break; case 5: - if (extensionFieldSetsExists) - { - ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); - TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; - break; - } // Just for compatibility, we will add array type support in IM later. TLVUnpackError = aDataTlv.GetDataPtr(const_cast(extensionFieldSets)); - if (CHIP_NO_ERROR == TLVUnpackError) - { - extensionFieldSetsExists = true; - validArgumentCount++; - } break; default: // Unsupported tag, ignore it. ChipLogProgress(Zcl, "Unknown TLV tag during processing."); break; } - if (TLVUnpackError != CHIP_NO_ERROR) - { - ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32, - TLV::TagNumFromTag(aDataTlv.GetTag()), TLVUnpackError); - break; - } } if (CHIP_END_OF_TLV == TLVError) @@ -4174,25 +3039,13 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. TLVError = CHIP_NO_ERROR; } - else - { - ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError); - } - // TODO(#5590) We should encode a response of status code for invalid TLV. if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) { // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. emberAfScenesClusterViewSceneResponseCallback(status, groupId, sceneId, transitionTime, const_cast(sceneName), extensionFieldSets); - } - else - { - apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, - Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); - ChipLogProgress( - Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32, - 6, validArgumentCount, TLVError, TLVUnpackError); + return; } break; } @@ -4201,10 +3054,20 @@ void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, En apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound, Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure); ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_SCENES_CLUSTER_ID); - break; + return; } } } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount == validArgumentCount) + { + apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, Protocols::SecureChannel::Id, + Protocols::SecureChannel::kProtocolCodeGeneralFailure); + ChipLogProgress(Zcl, + "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32 + " (last decoded tag = %" PRIu32, + 3, validArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } } } // namespace Scenes