Skip to content

Commit

Permalink
Send status report in IM server side when server encounter the error (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
yunhanw-google authored and pull[bot] committed Oct 27, 2023
1 parent bdd9af3 commit a764bc2
Show file tree
Hide file tree
Showing 12 changed files with 306 additions and 154 deletions.
2 changes: 2 additions & 0 deletions src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ static_library("app") {
"OperationalDeviceProxy.h",
"ReadClient.cpp",
"ReadHandler.cpp",
"StatusResponse.cpp",
"StatusResponse.h",
"WriteClient.cpp",
"WriteHandler.cpp",
"decoder.cpp",
Expand Down
24 changes: 17 additions & 7 deletions src/app/CommandSender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "Command.h"
#include "CommandHandler.h"
#include "InteractionModelEngine.h"
#include "StatusResponse.h"
#include <protocols/Protocols.h>
#include <protocols/interaction_model/Constants.h>

Expand Down Expand Up @@ -91,20 +92,29 @@ CHIP_ERROR CommandSender::OnMessageReceived(Messaging::ExchangeContext * apExcha
System::PacketBufferHandle && aPayload)
{
CHIP_ERROR err = CHIP_NO_ERROR;

StatusIB status(Protocols::InteractionModel::Status::Failure);
VerifyOrExit(apExchangeContext == mpExchangeCtx, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::InvokeCommandResponse),
err = CHIP_ERROR_INVALID_MESSAGE_TYPE);

err = ProcessInvokeResponse(std::move(aPayload));
if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::InvokeCommandResponse))
{
err = ProcessInvokeResponse(std::move(aPayload));
SuccessOrExit(err);
status.mStatus = Protocols::InteractionModel::Status::Success;
}
else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::StatusResponse))
{
err = StatusResponse::ProcessStatusResponse(std::move(aPayload), status);
SuccessOrExit(err);
}
else
{
err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
}

exit:
if (mpCallback != nullptr)
{
if (err != CHIP_NO_ERROR)
{
StatusIB status;
status.mStatus = Protocols::InteractionModel::Status::Failure;
mpCallback->OnError(this, status, err);
}
}
Expand Down
114 changes: 48 additions & 66 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ CHIP_ERROR InteractionModelEngine::NewReadClient(ReadClient ** const apReadClien
return err;
}
}

return CHIP_ERROR_NO_MEMORY;
}

Expand Down Expand Up @@ -263,7 +262,6 @@ CHIP_ERROR InteractionModelEngine::NewWriteClient(WriteClientHandle & apWriteCli
{
continue;
}

ReturnLogErrorOnFailure(writeClient.Init(mpExchangeMgr, apCallback));
apWriteClient.SetWriteClient(&writeClient);
return CHIP_NO_ERROR;
Expand All @@ -272,51 +270,34 @@ CHIP_ERROR InteractionModelEngine::NewWriteClient(WriteClientHandle & apWriteCli
return CHIP_ERROR_NO_MEMORY;
}

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

ChipLogDetail(InteractionModel, "Msg type %d not supported", aPayloadHeader.GetMessageType());

// Todo: Add status report
// err = SendStatusReport(ec, kChipProfile_Common, kStatus_UnsupportedMessage);
// SuccessOrExit(err);

apExchangeContext = nullptr;

// Todo: Fix the below check after the above status report is implemented.
if (nullptr != apExchangeContext)
{
apExchangeContext->Abort();
}
return err;
}

void InteractionModelEngine::OnDone(CommandHandler & apCommandObj)
{
mCommandHandlerObjs.ReleaseObject(&apCommandObj);
}

CHIP_ERROR InteractionModelEngine::OnInvokeCommandRequest(Messaging::ExchangeContext * apExchangeContext,
const PayloadHeader & aPayloadHeader,
System::PacketBufferHandle && aPayload)
System::PacketBufferHandle && aPayload,
Protocols::InteractionModel::Status & aStatus)
{
CommandHandler * commandHandler = mCommandHandlerObjs.CreateObject(this);
if (commandHandler == nullptr)
{
ChipLogProgress(InteractionModel, "no resource for Invoke interaction");
aStatus = Protocols::InteractionModel::Status::Busy;
return CHIP_ERROR_NO_MEMORY;
}
return commandHandler->OnInvokeCommandRequest(apExchangeContext, aPayloadHeader, std::move(aPayload));
ReturnErrorOnFailure(commandHandler->OnInvokeCommandRequest(apExchangeContext, aPayloadHeader, std::move(aPayload)));
aStatus = Protocols::InteractionModel::Status::Success;
return CHIP_NO_ERROR;
}

CHIP_ERROR InteractionModelEngine::OnReadInitialRequest(Messaging::ExchangeContext * apExchangeContext,
const PayloadHeader & aPayloadHeader,
System::PacketBufferHandle && aPayload,
ReadHandler::InteractionType aInteractionType)
ReadHandler::InteractionType aInteractionType,
Protocols::InteractionModel::Status & aStatus)
{
CHIP_ERROR err = CHIP_NO_ERROR;

ChipLogDetail(InteractionModel, "Received %s request",
aInteractionType == ReadHandler::InteractionType::Subscribe ? "Subscribe" : "Read");

Expand All @@ -329,10 +310,10 @@ CHIP_ERROR InteractionModelEngine::OnReadInitialRequest(Messaging::ExchangeConte
bool keepSubscriptions = true;
System::PacketBufferTLVReader reader;
reader.Init(aPayload.Retain());
SuccessOrExit(err = reader.Next());
ReturnErrorOnFailure(reader.Next());
SubscribeRequestMessage::Parser subscribeRequestParser;
SuccessOrExit(err = subscribeRequestParser.Init(reader));
err = subscribeRequestParser.GetKeepSubscriptions(&keepSubscriptions);
ReturnErrorOnFailure(subscribeRequestParser.Init(reader));
CHIP_ERROR err = subscribeRequestParser.GetKeepSubscriptions(&keepSubscriptions);
if (err == CHIP_NO_ERROR && !keepSubscriptions)
{
readHandler.Shutdown(ReadHandler::ShutdownOptions::AbortCurrentExchange);
Expand All @@ -344,49 +325,39 @@ CHIP_ERROR InteractionModelEngine::OnReadInitialRequest(Messaging::ExchangeConte
{
if (readHandler.IsFree())
{
err = readHandler.Init(mpExchangeMgr, mpDelegate, apExchangeContext, aInteractionType);
SuccessOrExit(err);
err = readHandler.OnReadInitialRequest(std::move(aPayload));
apExchangeContext = nullptr;
break;
ReturnErrorOnFailure(readHandler.Init(mpExchangeMgr, mpDelegate, apExchangeContext, aInteractionType));
ReturnErrorOnFailure(readHandler.OnReadInitialRequest(std::move(aPayload)));
aStatus = Protocols::InteractionModel::Status::Success;
return CHIP_NO_ERROR;
}
}

exit:
ChipLogProgress(InteractionModel, "no resource for %s interaction",
aInteractionType == ReadHandler::InteractionType::Subscribe ? "Subscribe" : "Read");
aStatus = Protocols::InteractionModel::Status::ResourceExhausted;

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

CHIP_ERROR InteractionModelEngine::OnWriteRequest(Messaging::ExchangeContext * apExchangeContext,
const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload)
const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload,
Protocols::InteractionModel::Status & aStatus)
{
CHIP_ERROR err = CHIP_NO_ERROR;

ChipLogDetail(InteractionModel, "Received Write request");

for (auto & writeHandler : mWriteHandlers)
{
if (writeHandler.IsFree())
{
err = writeHandler.Init(mpDelegate);
SuccessOrExit(err);
err = writeHandler.OnWriteRequest(apExchangeContext, std::move(aPayload));
apExchangeContext = nullptr;
break;
ReturnErrorOnFailure(writeHandler.Init(mpDelegate));
ReturnErrorOnFailure(writeHandler.OnWriteRequest(apExchangeContext, std::move(aPayload)));
aStatus = Protocols::InteractionModel::Status::Success;
return CHIP_NO_ERROR;
}
}

exit:

if (nullptr != apExchangeContext)
{
apExchangeContext->Abort();
}
return err;
ChipLogProgress(InteractionModel, "no resource for write interaction");
aStatus = Protocols::InteractionModel::Status::Busy;
return CHIP_NO_ERROR;
}

CHIP_ERROR InteractionModelEngine::OnUnsolicitedReportData(Messaging::ExchangeContext * apExchangeContext,
Expand All @@ -413,7 +384,6 @@ CHIP_ERROR InteractionModelEngine::OnUnsolicitedReportData(Messaging::ExchangeCo
{
continue;
}

return readClient.OnUnsolicitedReportData(apExchangeContext, std::move(aPayload));
}
return CHIP_NO_ERROR;
Expand All @@ -422,31 +392,43 @@ CHIP_ERROR InteractionModelEngine::OnUnsolicitedReportData(Messaging::ExchangeCo
CHIP_ERROR InteractionModelEngine::OnMessageReceived(Messaging::ExchangeContext * apExchangeContext,
const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload)
{
CHIP_ERROR err = CHIP_NO_ERROR;
Protocols::InteractionModel::Status status = Protocols::InteractionModel::Status::Failure;

if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::InvokeCommandRequest))
{
return OnInvokeCommandRequest(apExchangeContext, aPayloadHeader, std::move(aPayload));
SuccessOrExit(OnInvokeCommandRequest(apExchangeContext, aPayloadHeader, std::move(aPayload), status));
}
else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::ReadRequest))
{
return OnReadInitialRequest(apExchangeContext, aPayloadHeader, std::move(aPayload), ReadHandler::InteractionType::Read);
SuccessOrExit(OnReadInitialRequest(apExchangeContext, aPayloadHeader, std::move(aPayload),
ReadHandler::InteractionType::Read, status));
}
else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::WriteRequest))
{
return OnWriteRequest(apExchangeContext, aPayloadHeader, std::move(aPayload));
SuccessOrExit(OnWriteRequest(apExchangeContext, aPayloadHeader, std::move(aPayload), status));
}
else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::SubscribeRequest))
{
return OnReadInitialRequest(apExchangeContext, aPayloadHeader, std::move(aPayload),
ReadHandler::InteractionType::Subscribe);
SuccessOrExit(OnReadInitialRequest(apExchangeContext, aPayloadHeader, std::move(aPayload),
ReadHandler::InteractionType::Subscribe, status));
}
else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::ReportData))
{
return OnUnsolicitedReportData(apExchangeContext, aPayloadHeader, std::move(aPayload));
ReturnErrorOnFailure(OnUnsolicitedReportData(apExchangeContext, aPayloadHeader, std::move(aPayload)));
status = Protocols::InteractionModel::Status::Success;
}
else
{
return OnUnknownMsgType(apExchangeContext, aPayloadHeader, std::move(aPayload));
ChipLogProgress(InteractionModel, "Msg type %d not supported", aPayloadHeader.GetMessageType());
}

exit:
if (status != Protocols::InteractionModel::Status::Success)
{
err = StatusResponse::SendStatusResponse(status, apExchangeContext, false /*aExpectResponse*/);
}
return err;
}

void InteractionModelEngine::OnResponseTimeout(Messaging::ExchangeContext * ec)
Expand Down
24 changes: 14 additions & 10 deletions src/app/InteractionModelEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,14 @@
#include <app/InteractionModelDelegate.h>
#include <app/ReadClient.h>
#include <app/ReadHandler.h>
#include <app/StatusResponse.h>
#include <app/WriteClient.h>
#include <app/WriteHandler.h>
#include <app/reporting/Engine.h>
#include <app/util/basic-types.h>

namespace chip {
namespace app {

static constexpr size_t kMaxSecureSduLengthBytes = 1024;

/**
* @class InteractionModelEngine
*
Expand Down Expand Up @@ -202,28 +200,34 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate, public Comman

void OnDone(CommandHandler & apCommandObj) override;

CHIP_ERROR OnUnknownMsgType(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader,
System::PacketBufferHandle && aPayload);
/**
* Called when Interaction Model receives a Command Request message. Errors processing
* the Command Request are handled entirely within this function. The caller pre-sets status to failure and the callee is
* expected to set it to success if it does not want an automatic status response message to be sent.
*/
CHIP_ERROR OnInvokeCommandRequest(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader,
System::PacketBufferHandle && aPayload);
System::PacketBufferHandle && aPayload, Protocols::InteractionModel::Status & aStatus);
CHIP_ERROR OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader,
System::PacketBufferHandle && aPayload) override;
void OnResponseTimeout(Messaging::ExchangeContext * ec) override;

/**
* Called when Interaction Model receives a Read Request message. Errors processing
* the Read Request are handled entirely within this function.
* the Read Request are handled entirely within this function. The caller pre-sets status to failure and the callee is
* expected to set it to success if it does not want an automatic status response message to be sent.
*/

CHIP_ERROR OnReadInitialRequest(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader,
System::PacketBufferHandle && aPayload, ReadHandler::InteractionType aInteractionType);
System::PacketBufferHandle && aPayload, ReadHandler::InteractionType aInteractionType,
Protocols::InteractionModel::Status & aStatus);

/**
* Called when Interaction Model receives a Write Request message. Errors processing
* the Write Request are handled entirely within this function.
* the Write Request are handled entirely within this function. The caller pre-sets status to failure and the callee is
* expected to set it to success if it does not want an automatic status response message to be sent.
*/
CHIP_ERROR OnWriteRequest(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader,
System::PacketBufferHandle && aPayload);
System::PacketBufferHandle && aPayload, Protocols::InteractionModel::Status & aStatus);

/**This function handles processing of un-solicited ReportData messages on the client, which can
* only occur post subscription establishment
Expand Down
Loading

0 comments on commit a764bc2

Please sign in to comment.