-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[IM] Write Chunking Support (#13641)
* [IM] Implement write chunking with set+append for large lists * Python API update * Update LongListAttribute * Update TestSuite * Add more tests * Fix WriteClient construct call * Run Codegen * Address comments * Restyle * Fix test * Run Codegen * Fix dirty merge * Address comments * Update access-control-server * Fix merge * Updated code-gen * Address comments * Fix unclean merge * Fix GroupWrite Encoding * Fix merge and make access-control-server diff readable * Fix dirty merge * Update group-key-mgmt-server * Fix GroupWrite attribute path on the server side * Adapt WriteHandler for #14821 * Add ACL check cache * Resolve comments * Fix typo and fix merge * Fix * Comment out #if CONFIG_IM_BUILD_FOR_UNIT_TEST in WriteClient.h * Comment out #if CONFIG_IM_BUILD_FOR_UNIT_TEST in WriteClient.h Co-authored-by: Jerry Johns <[email protected]>
- Loading branch information
Showing
46 changed files
with
4,917 additions
and
3,372 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* | ||
* Copyright (c) 2022 Project CHIP Authors | ||
* All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <access/Privilege.h> | ||
#include <app/ConcreteAttributePath.h> | ||
|
||
namespace chip { | ||
namespace app { | ||
|
||
/** | ||
* AttributeAccessToken records the privilege granted for accessing the specified attribute. This struct is used in chunked write | ||
* to avoid losing privilege when updating ACL items. | ||
*/ | ||
struct AttributeAccessToken | ||
{ | ||
ConcreteAttributePath mPath; | ||
Access::Privilege mPrivilege; | ||
|
||
bool operator==(const AttributeAccessToken & other) const { return mPath == other.mPath && mPrivilege == other.mPrivilege; } | ||
|
||
bool Matches(const ConcreteAttributePath & aPath, const Access::Privilege & aPrivilege) const | ||
{ | ||
return mPath == aPath && mPrivilege == aPrivilege; | ||
} | ||
}; | ||
|
||
} // namespace app | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* | ||
* Copyright (c) 2022 Project CHIP Authors | ||
* All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include <app/ChunkedWriteCallback.h> | ||
|
||
namespace chip { | ||
namespace app { | ||
|
||
void ChunkedWriteCallback::OnResponse(const WriteClient * apWriteClient, const ConcreteDataAttributePath & aPath, StatusIB aStatus) | ||
{ | ||
// We may send a chunked list. To make the behavior consistent whether a list is being chunked or not, | ||
// we merge the write responses for a chunked list here and provide our consumer with a single status response. | ||
if (mLastAttributePath.HasValue()) | ||
{ | ||
// This is not the first write response. | ||
if (IsAppendingToLastItem(aPath)) | ||
{ | ||
// This is a response on the same path as what we already have stored. Report the first | ||
// failure status we encountered, and ignore subsequent ones. | ||
if (mAttributeStatus.IsSuccess()) | ||
{ | ||
mAttributeStatus = aStatus; | ||
} | ||
return; | ||
} | ||
else | ||
{ | ||
// This is a response to another attribute write. Report the final result of last attribute write. | ||
callback->OnResponse(apWriteClient, mLastAttributePath.Value(), mAttributeStatus); | ||
} | ||
} | ||
|
||
// This is the first report for a new attribute. We assume it will never be a list item operation. | ||
if (aPath.IsListItemOperation()) | ||
{ | ||
aStatus = StatusIB(CHIP_ERROR_INCORRECT_STATE); | ||
} | ||
|
||
mLastAttributePath.SetValue(aPath); | ||
mAttributeStatus = aStatus; | ||
// For the last status in the response, we will call the application callback in OnDone() | ||
} | ||
|
||
void ChunkedWriteCallback::OnError(const WriteClient * apWriteClient, CHIP_ERROR aError) | ||
{ | ||
callback->OnError(apWriteClient, aError); | ||
} | ||
|
||
void ChunkedWriteCallback::OnDone(WriteClient * apWriteClient) | ||
{ | ||
if (mLastAttributePath.HasValue()) | ||
{ | ||
// We have a cached status that has yet to be reported to the application so report it now. | ||
// If we failed to receive the response, or we received a malformed response, OnResponse won't be called, | ||
// mLastAttributePath will be Missing() in this case. | ||
callback->OnResponse(apWriteClient, mLastAttributePath.Value(), mAttributeStatus); | ||
} | ||
|
||
callback->OnDone(apWriteClient); | ||
} | ||
|
||
bool ChunkedWriteCallback::IsAppendingToLastItem(const ConcreteDataAttributePath & aPath) | ||
{ | ||
if (!aPath.IsListItemOperation()) | ||
{ | ||
return false; | ||
} | ||
if (!mLastAttributePath.HasValue() || !(mLastAttributePath.Value() == aPath)) | ||
{ | ||
return false; | ||
} | ||
return aPath.mListOp == ConcreteDataAttributePath::ListOperation::AppendItem; | ||
} | ||
|
||
} // namespace app | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* | ||
* Copyright (c) 2022 Project CHIP Authors | ||
* All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <app/WriteClient.h> | ||
|
||
namespace chip { | ||
namespace app { | ||
|
||
/* | ||
* This is an adapter that intercepts calls that deliver status codes from the WriteClient and | ||
* selectively "merge"s the status codes for a chunked list write as follows: | ||
* - If the whole list was successfully written, callback->OnResponse will be called with success. | ||
* - If any element in the list was not successfully written, callback->OnResponse will be called with the first error received. | ||
* - callback->OnResponse will always have NotList as mListOp since we have merged the chunked responses. | ||
* The merge logic assumes all list operations are part of list chunking. | ||
*/ | ||
class ChunkedWriteCallback : public WriteClient::Callback | ||
{ | ||
public: | ||
ChunkedWriteCallback(WriteClient::Callback * apCallback) : callback(apCallback) {} | ||
|
||
void OnResponse(const WriteClient * apWriteClient, const ConcreteDataAttributePath & aPath, StatusIB status) override; | ||
void OnError(const WriteClient * apWriteClient, CHIP_ERROR aError) override; | ||
void OnDone(WriteClient * apWriteClient) override; | ||
|
||
private: | ||
bool IsAppendingToLastItem(const ConcreteDataAttributePath & aPath); | ||
|
||
// We are using the casts between ConcreteAttributePath and ConcreteDataAttributePath, then all paths passed to upper | ||
// applications will always have NotList as mListOp. | ||
Optional<ConcreteAttributePath> mLastAttributePath; | ||
StatusIB mAttributeStatus; | ||
|
||
WriteClient::Callback * callback; | ||
}; | ||
|
||
} // namespace app | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.