Skip to content

Commit

Permalink
Add a test-only API to allow subscribing with invalid intervals. (#18855
Browse files Browse the repository at this point in the history
)

This allows chip-tool to test server behavior when
MinIntervalFloor > MaxIntervalCeiling.

Fixes #18839
  • Loading branch information
bzbarsky-apple authored May 27, 2022
1 parent dbc91b7 commit 32866c0
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 14 deletions.
26 changes: 14 additions & 12 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -840,11 +840,16 @@ CHIP_ERROR ReadClient::SendAutoResubscribeRequest(ReadPrepareParams && aReadPrep
return err;
}

CHIP_ERROR ReadClient::SendSubscribeRequest(ReadPrepareParams & aReadPrepareParams)
CHIP_ERROR ReadClient::SendSubscribeRequest(const ReadPrepareParams & aReadPrepareParams)
{
CHIP_ERROR err = CHIP_NO_ERROR;
VerifyOrReturnError(aReadPrepareParams.mMinIntervalFloorSeconds <= aReadPrepareParams.mMaxIntervalCeilingSeconds,
CHIP_ERROR_INVALID_ARGUMENT);
return SendSubscribeRequestImpl(aReadPrepareParams);
}

VerifyOrReturnError(ClientState::Idle == mState, err = CHIP_ERROR_INCORRECT_STATE);
CHIP_ERROR ReadClient::SendSubscribeRequestImpl(const ReadPrepareParams & aReadPrepareParams)
{
VerifyOrReturnError(ClientState::Idle == mState, CHIP_ERROR_INCORRECT_STATE);

// Todo: Remove the below, Update span in ReadPrepareParams
Span<AttributePathParams> attributePaths(aReadPrepareParams.mpAttributePathParamsList,
Expand All @@ -853,9 +858,6 @@ CHIP_ERROR ReadClient::SendSubscribeRequest(ReadPrepareParams & aReadPreparePara
Span<DataVersionFilter> dataVersionFilters(aReadPrepareParams.mpDataVersionFilterList,
aReadPrepareParams.mDataVersionFilterListSize);

VerifyOrReturnError(aReadPrepareParams.mMinIntervalFloorSeconds <= aReadPrepareParams.mMaxIntervalCeilingSeconds,
err = CHIP_ERROR_INVALID_ARGUMENT);

System::PacketBufferHandle msgBuf;
System::PacketBufferTLVWriter writer;
SubscribeRequestMessage::Builder request;
Expand All @@ -870,27 +872,27 @@ CHIP_ERROR ReadClient::SendSubscribeRequest(ReadPrepareParams & aReadPreparePara
if (!attributePaths.empty())
{
AttributePathIBs::Builder & attributePathListBuilder = request.CreateAttributeRequests();
ReturnErrorOnFailure(err = attributePathListBuilder.GetError());
ReturnErrorOnFailure(attributePathListBuilder.GetError());
ReturnErrorOnFailure(GenerateAttributePaths(attributePathListBuilder, attributePaths));
}

if (!eventPaths.empty())
{
EventPathIBs::Builder & eventPathListBuilder = request.CreateEventRequests();
ReturnErrorOnFailure(err = eventPathListBuilder.GetError());
ReturnErrorOnFailure(eventPathListBuilder.GetError());
ReturnErrorOnFailure(GenerateEventPaths(eventPathListBuilder, eventPaths));

Optional<EventNumber> eventMin;
ReturnErrorOnFailure(GetMinEventNumber(aReadPrepareParams, eventMin));
if (eventMin.HasValue())
{
EventFilterIBs::Builder & eventFilters = request.CreateEventFilters();
ReturnErrorOnFailure(err = request.GetError());
ReturnErrorOnFailure(request.GetError());
ReturnErrorOnFailure(eventFilters.GenerateEventFilter(eventMin.Value()));
}
}

ReturnErrorOnFailure(err = request.IsFabricFiltered(aReadPrepareParams.mIsFabricFiltered).GetError());
ReturnErrorOnFailure(request.IsFabricFiltered(aReadPrepareParams.mIsFabricFiltered).GetError());

bool encodedDataVersionList = false;
TLV::TLVWriter backup;
Expand All @@ -912,13 +914,13 @@ CHIP_ERROR ReadClient::SendSubscribeRequest(ReadPrepareParams & aReadPreparePara
request.Rollback(backup);
}

ReturnErrorOnFailure(err = request.EndOfSubscribeRequestMessage().GetError());
ReturnErrorOnFailure(request.EndOfSubscribeRequestMessage().GetError());
ReturnErrorOnFailure(writer.Finalize(&msgBuf));

VerifyOrReturnError(aReadPrepareParams.mSessionHolder, CHIP_ERROR_MISSING_SECURE_SESSION);

mpExchangeCtx = mpExchangeMgr->NewContext(aReadPrepareParams.mSessionHolder.Get().Value(), this);
VerifyOrReturnError(mpExchangeCtx != nullptr, err = CHIP_ERROR_NO_MEMORY);
VerifyOrReturnError(mpExchangeCtx != nullptr, CHIP_ERROR_NO_MEMORY);
mpExchangeCtx->SetResponseTimeout(kImMessageTimeout);

ReturnErrorOnFailure(mpExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::SubscribeRequest, std::move(msgBuf),
Expand Down
15 changes: 14 additions & 1 deletion src/app/ReadClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,16 @@ class ReadClient : public Messaging::ExchangeDelegate
// that's the only case when the consumer moved a ReadParams into the client.
CHIP_ERROR SendAutoResubscribeRequest(ReadPrepareParams && aReadPrepareParams);

// Like SendSubscribeRequest, but allows sending certain forms of invalid
// subscribe requests that servers are expected to reject, for testing
// purposes. Should only be called from tests.
#if CONFIG_IM_BUILD_FOR_UNIT_TEST
CHIP_ERROR SendSubscribeRequestWithoutValidation(const ReadPrepareParams & aReadPrepareParams)
{
return SendSubscribeRequestImpl(aReadPrepareParams);
}
#endif // CONFIG_IM_BUILD_FOR_UNIT_TEST

private:
friend class TestReadInteraction;
friend class InteractionModelEngine;
Expand Down Expand Up @@ -358,7 +368,10 @@ class ReadClient : public Messaging::ExchangeDelegate
bool ResubscribeIfNeeded();
// Specialized request-sending functions.
CHIP_ERROR SendReadRequest(ReadPrepareParams & aReadPrepareParams);
CHIP_ERROR SendSubscribeRequest(ReadPrepareParams & aSubscribePrepareParams);
// SendSubscribeRequest performs som validation on aSubscribePrepareParams
// and then calls SendSubscribeRequestImpl.
CHIP_ERROR SendSubscribeRequest(const ReadPrepareParams & aSubscribePrepareParams);
CHIP_ERROR SendSubscribeRequestImpl(const ReadPrepareParams & aSubscribePrepareParams);
void UpdateDataVersionFilters(const ConcreteDataAttributePath & aPath);
static void OnResubscribeTimerCallback(System::Layer * apSystemLayer, void * apAppState);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,16 @@ CHIP_ERROR InteractionModelReports::ReportAttribute(DeviceProxy * device, std::v

auto client = std::make_unique<ReadClient>(InteractionModelEngine::GetInstance(), device->GetExchangeManager(),
mBufferedReadAdapter, interactionType);
ReturnErrorOnFailure(client->SendRequest(params));
if (interactionType == ReadClient::InteractionType::Read)
{
ReturnErrorOnFailure(client->SendRequest(params));
}
else
{
// We want to allow certain kinds of spec-invalid subscriptions so we
// can test how the server reacts to them.
ReturnErrorOnFailure(client->SendSubscribeRequestWithoutValidation(params));
}
mReadClients.push_back(std::move(client));
return CHIP_NO_ERROR;
}
Expand Down

0 comments on commit 32866c0

Please sign in to comment.