Skip to content

Commit

Permalink
Add initial IM write client/handler (#7730)
Browse files Browse the repository at this point in the history
  • Loading branch information
yunhanw-google authored and pan- committed Jun 30, 2023
1 parent 7c94f57 commit d7a6c2e
Show file tree
Hide file tree
Showing 21 changed files with 1,534 additions and 24 deletions.
2 changes: 2 additions & 0 deletions src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ static_library("app") {
"MessageDef/WriteResponse.cpp",
"ReadClient.cpp",
"ReadHandler.cpp",
"WriteClient.cpp",
"WriteHandler.cpp",
"decoder.cpp",
"encoder-common.cpp",
"reporting/Engine.cpp",
Expand Down
2 changes: 1 addition & 1 deletion src/app/CommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void CommandHandler::OnMessageReceived(Messaging::ExchangeContext * ec, const Pa
err = ProcessCommandMessage(std::move(payload), CommandRoleId::HandlerId);
SuccessOrExit(err);

SendCommandResponse();
err = SendCommandResponse();

exit:
ChipLogFunctError(err);
Expand Down
39 changes: 39 additions & 0 deletions src/app/InteractionModelDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#pragma once

#include <app/AttributePathParams.h>
#include <core/CHIPCore.h>
#include <core/CHIPTLV.h>
#include <messaging/ExchangeContext.h>
Expand All @@ -33,6 +34,7 @@
namespace chip {
namespace app {
class ReadClient;
class WriteClient;
class CommandSender;

/**
Expand Down Expand Up @@ -134,6 +136,43 @@ class InteractionModelDelegate
return CHIP_ERROR_NOT_IMPLEMENTED;
}

/**
* Notification that a WriteClient has received an Write Response containing a status code.
*/
virtual CHIP_ERROR WriteResponseStatus(const WriteClient * apWriteClient,
const Protocols::SecureChannel::GeneralStatusCode aGeneralCode,
const uint32_t aProtocolId, const uint16_t aProtocolCode,
AttributePathParams & aAttributePathParams, uint8_t aCommandIndex)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

/**
* Notification that a Write Response has already been processed.
*/
virtual CHIP_ERROR WriteResponseProcessed(const WriteClient * apWriteClient) { return CHIP_ERROR_NOT_IMPLEMENTED; }

/**
* Notification that a Write Client has received an Write Response and fails to process a attribute data element in that
* write response
*/
virtual CHIP_ERROR WriteResponseProtocolError(const WriteClient * apWriteClient, uint8_t aAttributeIndex)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

/**
* Notification that a write client encountered an asynchronous failure.
* @param[in] aCWriteClient write interactions
* @param[in] aError A error that could be CHIP_ERROR_TIMEOUT when write client fails to receive, or other error when
* fail to process write response.
* @retval # CHIP_ERROR_NOT_IMPLEMENTED if not implemented
*/
virtual CHIP_ERROR WriteResponseError(const WriteClient * apWriteClient, CHIP_ERROR aError)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

virtual ~InteractionModelDelegate() = default;
};

Expand Down
77 changes: 76 additions & 1 deletion src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,28 @@ void InteractionModelEngine::Shutdown()
}
}

for (auto & writeClient : mWriteClients)
{
if (!writeClient.IsFree())
{
writeClient.Shutdown();
}
}

for (auto & writeHandler : mWriteHandlers)
{
if (!writeHandler.IsFree())
{
writeHandler.Shutdown();
}
}

for (uint32_t index = 0; index < IM_SERVER_MAX_NUM_PATH_GROUPS; index++)
{
mClusterInfoPool[index].mpNext = nullptr;
mClusterInfoPool[index].ClearDirty();
}

mpNextAvailableClusterInfo = nullptr;
}

Expand Down Expand Up @@ -151,6 +168,25 @@ CHIP_ERROR InteractionModelEngine::NewReadClient(ReadClient ** const apReadClien
return err;
}

CHIP_ERROR InteractionModelEngine::NewWriteClient(WriteClient ** const apWriteClient)
{
*apWriteClient = nullptr;

for (auto & writeClient : mWriteClients)
{
if (!writeClient.IsFree())
{
continue;
}

ReturnErrorOnFailure(writeClient.Init(mpExchangeMgr, mpDelegate));
*apWriteClient = &writeClient;
return CHIP_NO_ERROR;
}

return CHIP_ERROR_NO_MEMORY;
}

void InteractionModelEngine::OnUnknownMsgType(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload)
{
Expand Down Expand Up @@ -230,6 +266,35 @@ void InteractionModelEngine::OnReadRequest(Messaging::ExchangeContext * apExchan
}
}

void InteractionModelEngine::OnWriteRequest(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload)
{
CHIP_ERROR err = CHIP_NO_ERROR;

ChipLogDetail(DataManagement, "Receive Write request");

for (auto & writeHandler : mWriteHandlers)
{
if (writeHandler.IsFree())
{
err = writeHandler.Init(mpDelegate);
SuccessOrExit(err);
err = writeHandler.OnWriteRequest(apExchangeContext, std::move(aPayload));
SuccessOrExit(err);
apExchangeContext = nullptr;
break;
}
}

exit:
ChipLogFunctError(err);

if (nullptr != apExchangeContext)
{
apExchangeContext->Abort();
}
}

void InteractionModelEngine::OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload)
{
Expand All @@ -242,6 +307,10 @@ void InteractionModelEngine::OnMessageReceived(Messaging::ExchangeContext * apEx
{
OnReadRequest(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
}
else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::WriteRequest))
{
OnWriteRequest(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
}
else
{
OnUnknownMsgType(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
Expand All @@ -267,7 +336,8 @@ CHIP_ERROR __attribute__((weak)) ReadSingleClusterData(ClusterInfo & aClusterInf
return CHIP_NO_ERROR;
}

CHIP_ERROR __attribute__((weak)) WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader)
CHIP_ERROR __attribute__((weak))
WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader, WriteHandler * apWriteHandler)
{
ChipLogDetail(DataManagement,
"Received Cluster Attribute: Cluster=%" PRIx16 " NodeId=0x" ChipLogFormatX64 " Endpoint=%" PRIx8
Expand All @@ -284,6 +354,11 @@ uint16_t InteractionModelEngine::GetReadClientArrayIndex(const ReadClient * cons
return static_cast<uint16_t>(apReadClient - mReadClients);
}

uint16_t InteractionModelEngine::GetWriteClientArrayIndex(const WriteClient * const apWriteClient) const
{
return static_cast<uint16_t>(apWriteClient - mWriteClients);
}

void InteractionModelEngine::ReleaseClusterInfoList(ClusterInfo *& aClusterInfo)
{
ClusterInfo * lastClusterInfo = aClusterInfo;
Expand Down
28 changes: 27 additions & 1 deletion src/app/InteractionModelEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include <app/InteractionModelDelegate.h>
#include <app/ReadClient.h>
#include <app/ReadHandler.h>
#include <app/WriteClient.h>
#include <app/WriteHandler.h>
#include <app/reporting/Engine.h>
#include <app/util/basic-types.h>

Expand All @@ -54,6 +56,8 @@
#define CHIP_MAX_NUM_READ_HANDLER 1
#define CHIP_MAX_REPORTS_IN_FLIGHT 1
#define IM_SERVER_MAX_NUM_PATH_GROUPS 8
#define CHIP_MAX_NUM_WRITE_CLIENT 1
#define CHIP_MAX_NUM_WRITE_HANDLER 1

namespace chip {
namespace app {
Expand Down Expand Up @@ -122,6 +126,17 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate
*/
CHIP_ERROR NewReadClient(ReadClient ** const apReadClient);

/**
* Retrieve a WriteClient that the SDK consumer can use to send do a write. If the call succeeds, the consumer
* is responsible for calling Shutdown() on the WriteClient once it's done using it.
*
* @param[out] apWriteClient A pointer to the WriteClient object.
*
* @retval #CHIP_ERROR_INCORRECT_STATE If there is no WriteClient available
* @retval #CHIP_NO_ERROR On success.
*/
CHIP_ERROR NewWriteClient(WriteClient ** const apWriteClient);

/**
* Get read client index in mReadClients
*
Expand All @@ -131,6 +146,8 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate
*/
uint16_t GetReadClientArrayIndex(const ReadClient * const apReadClient) const;

uint16_t GetWriteClientArrayIndex(const WriteClient * const apWriteClient) const;

reporting::Engine & GetReportingEngine() { return mReportingEngine; }

void ReleaseClusterInfoList(ClusterInfo *& aClusterInfo);
Expand All @@ -153,12 +170,21 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate
void OnReadRequest(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload);

/**
* Called when Interaction Model receives a Write Request message. Errors processing
* the Write Request are handled entirely within this function.
*/
void OnWriteRequest(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload);

Messaging::ExchangeManager * mpExchangeMgr = nullptr;
InteractionModelDelegate * mpDelegate = nullptr;
CommandHandler mCommandHandlerObjs[CHIP_MAX_NUM_COMMAND_HANDLER];
CommandSender mCommandSenderObjs[CHIP_MAX_NUM_COMMAND_SENDER];
ReadClient mReadClients[CHIP_MAX_NUM_READ_CLIENT];
ReadHandler mReadHandlers[CHIP_MAX_NUM_READ_HANDLER];
WriteClient mWriteClients[CHIP_MAX_NUM_WRITE_CLIENT];
WriteHandler mWriteHandlers[CHIP_MAX_NUM_WRITE_HANDLER];
reporting::Engine mReportingEngine;
ClusterInfo mClusterInfoPool[IM_SERVER_MAX_NUM_PATH_GROUPS];
ClusterInfo * mpNextAvailableClusterInfo = nullptr;
Expand All @@ -179,6 +205,6 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC
*/
bool ServerClusterCommandExists(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId);
CHIP_ERROR ReadSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVWriter & aWriter);
CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader);
CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader, WriteHandler * apWriteHandler);
} // namespace app
} // namespace chip
5 changes: 5 additions & 0 deletions src/app/MessageDef/AttributeDataList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ AttributeDataElement::Builder & AttributeDataList::Builder::CreateAttributeDataE
return mAttributeDataElementBuilder;
}

AttributeDataElement::Builder & AttributeDataList::Builder::GetAttributeDataElementBuilder()
{
return mAttributeDataElementBuilder;
}

AttributeDataList::Builder & AttributeDataList::Builder::EndOfAttributeDataList()
{
EndOfContainer();
Expand Down
2 changes: 2 additions & 0 deletions src/app/MessageDef/AttributeDataList.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class Builder : public ListBuilder
*/
AttributeDataElement::Builder & CreateAttributeDataElementBuilder();

AttributeDataElement::Builder & GetAttributeDataElementBuilder();

/**
* @brief Mark the end of this AttributeDataList
*
Expand Down
5 changes: 5 additions & 0 deletions src/app/MessageDef/WriteRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@ WriteRequest::Builder & WriteRequest::Builder::MoreChunkedMessages(const bool aM
return *this;
}

AttributeDataList::Builder & WriteRequest::Builder::GetAttributeDataListBuilder()
{
return mAttributeDataListBuilder;
}

WriteRequest::Builder & WriteRequest::Builder::EndOfWriteRequest()
{
EndOfContainer();
Expand Down
3 changes: 3 additions & 0 deletions src/app/MessageDef/WriteRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ class Builder : public chip::app::Builder
* @return A reference to *this
*/
WriteRequest::Builder & MoreChunkedMessages(const bool aMoreChunkedMessages);

AttributeDataList::Builder & GetAttributeDataListBuilder();

/**
* @brief Mark the end of this WriteRequest
*
Expand Down
5 changes: 5 additions & 0 deletions src/app/MessageDef/WriteResponse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ AttributeStatusList::Builder & WriteResponse::Builder::CreateAttributeStatusList
return mAttributeStatusListBuilder;
}

AttributeStatusList::Builder & WriteResponse::Builder::GetAttributeStatusListBuilder()
{
return mAttributeStatusListBuilder;
}

WriteResponse::Builder & WriteResponse::Builder::EndOfWriteResponse()
{
EndOfContainer();
Expand Down
7 changes: 7 additions & 0 deletions src/app/MessageDef/WriteResponse.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ class Builder : public chip::app::Builder
*/
AttributeStatusList::Builder & CreateAttributeStatusListBuilder();

/**
* @brief Get reference to AttributeStatusList::Builder
*
* @return A reference to AttributeStatusList::Builder
*/
AttributeStatusList::Builder & GetAttributeStatusListBuilder();

/**
* @brief Mark the end of this WriteResponse
*
Expand Down
2 changes: 0 additions & 2 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,6 @@ CHIP_ERROR ReadClient::ProcessAttributeDataList(TLV::TLVReader & aAttributeDataL

err = element.GetData(&dataReader);
SuccessOrExit(err);
err = WriteSingleClusterData(clusterInfo, dataReader);
SuccessOrExit(err);
}

if (CHIP_END_OF_TLV == err)
Expand Down
2 changes: 0 additions & 2 deletions src/app/ReadHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ CHIP_ERROR ReadHandler::OnReadRequest(Messaging::ExchangeContext * apExchangeCon

mpExchangeCtx = apExchangeContext;
err = ProcessReadRequest(std::move(aPayload));
SuccessOrExit(err);

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogFunctError(err);
Expand Down
Loading

0 comments on commit d7a6c2e

Please sign in to comment.