Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #include "TransferFacilitator.h"
19 :
20 : #include <lib/core/CHIPError.h>
21 : #include <lib/support/BitFlags.h>
22 : #include <messaging/ExchangeContext.h>
23 : #include <messaging/ExchangeDelegate.h>
24 : #include <platform/CHIPDeviceLayer.h>
25 : #include <protocols/bdx/BdxTransferSession.h>
26 : #include <system/SystemClock.h>
27 : #include <system/SystemLayer.h>
28 :
29 : namespace chip {
30 : namespace bdx {
31 :
32 : constexpr System::Clock::Timeout TransferFacilitator::kDefaultPollFreq;
33 : constexpr System::Clock::Timeout TransferFacilitator::kImmediatePollDelay;
34 :
35 0 : TransferFacilitator::~TransferFacilitator()
36 : {
37 0 : ResetTransfer();
38 0 : }
39 :
40 0 : void TransferFacilitator::ResetTransfer()
41 : {
42 0 : mTransfer.Reset();
43 0 : ChipLogProgress(BDX, "Stop polling for messages");
44 :
45 0 : VerifyOrReturn(mSystemLayer != nullptr);
46 0 : mSystemLayer->CancelTimer(PollTimerHandler, this);
47 0 : mSystemLayer = nullptr;
48 : }
49 :
50 0 : CHIP_ERROR TransferFacilitator::OnMessageReceived(chip::Messaging::ExchangeContext * ec, const chip::PayloadHeader & payloadHeader,
51 : chip::System::PacketBufferHandle && payload)
52 : {
53 0 : if (mExchangeCtx == nullptr)
54 : {
55 0 : mExchangeCtx = ec;
56 : }
57 :
58 0 : ChipLogDetail(BDX, "%s: message " ChipLogFormatMessageType " protocol " ChipLogFormatProtocolId, __FUNCTION__,
59 : payloadHeader.GetMessageType(), ChipLogValueProtocolId(payloadHeader.GetProtocolID()));
60 : CHIP_ERROR err =
61 0 : mTransfer.HandleMessageReceived(payloadHeader, std::move(payload), System::SystemClock().GetMonotonicTimestamp());
62 0 : if (err != CHIP_NO_ERROR)
63 : {
64 0 : ChipLogError(BDX, "failed to handle message: %" CHIP_ERROR_FORMAT, err.Format());
65 : }
66 :
67 : // Almost every BDX message will follow up with a response on the exchange. Even messages that might signify the end of a
68 : // transfer could necessitate a response if they are received at the wrong time.
69 : // For this reason, it is left up to the application logic to call ExchangeContext::Close() when it has determined that the
70 : // transfer is finished.
71 0 : mExchangeCtx->WillSendMessage();
72 :
73 0 : return err;
74 : }
75 :
76 0 : void TransferFacilitator::OnResponseTimeout(Messaging::ExchangeContext * ec)
77 : {
78 0 : ChipLogError(BDX, "%s, ec: " ChipLogFormatExchange, __FUNCTION__, ChipLogValueExchange(ec));
79 0 : mExchangeCtx = nullptr;
80 0 : mTransfer.Reset();
81 0 : }
82 :
83 0 : void TransferFacilitator::PollTimerHandler(chip::System::Layer * systemLayer, void * appState)
84 : {
85 0 : VerifyOrReturn(appState != nullptr);
86 0 : static_cast<TransferFacilitator *>(appState)->PollForOutput();
87 : }
88 :
89 0 : void TransferFacilitator::PollForOutput()
90 : {
91 0 : TransferSession::OutputEvent outEvent;
92 0 : mTransfer.PollOutput(outEvent, System::SystemClock().GetMonotonicTimestamp());
93 0 : HandleTransferSessionOutput(outEvent);
94 :
95 0 : VerifyOrReturn(mSystemLayer != nullptr, ChipLogError(BDX, "%s mSystemLayer is null", __FUNCTION__));
96 0 : mSystemLayer->StartTimer(mPollFreq, PollTimerHandler, this);
97 0 : }
98 :
99 0 : void TransferFacilitator::ScheduleImmediatePoll()
100 : {
101 0 : VerifyOrReturn(mSystemLayer != nullptr, ChipLogError(BDX, "%s mSystemLayer is null", __FUNCTION__));
102 0 : mSystemLayer->StartTimer(System::Clock::Milliseconds32(kImmediatePollDelay), PollTimerHandler, this);
103 : }
104 :
105 0 : CHIP_ERROR Responder::PrepareForTransfer(System::Layer * layer, TransferRole role, BitFlags<TransferControlFlags> xferControlOpts,
106 : uint16_t maxBlockSize, System::Clock::Timeout timeout, System::Clock::Timeout pollFreq)
107 : {
108 0 : VerifyOrReturnError(layer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
109 :
110 0 : mPollFreq = pollFreq;
111 0 : mSystemLayer = layer;
112 :
113 0 : ReturnErrorOnFailure(mTransfer.WaitForTransfer(role, xferControlOpts, maxBlockSize, timeout));
114 :
115 0 : ChipLogProgress(BDX, "Start polling for messages");
116 0 : mSystemLayer->StartTimer(mPollFreq, PollTimerHandler, this);
117 0 : return CHIP_NO_ERROR;
118 : }
119 :
120 0 : CHIP_ERROR Initiator::InitiateTransfer(System::Layer * layer, TransferRole role, const TransferSession::TransferInitData & initData,
121 : System::Clock::Timeout timeout, System::Clock::Timeout pollFreq)
122 : {
123 0 : VerifyOrReturnError(layer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
124 :
125 0 : mPollFreq = pollFreq;
126 0 : mSystemLayer = layer;
127 :
128 0 : ReturnErrorOnFailure(mTransfer.StartTransfer(role, initData, timeout));
129 :
130 0 : mSystemLayer->StartTimer(mPollFreq, PollTimerHandler, this);
131 0 : return CHIP_NO_ERROR;
132 : }
133 :
134 : } // namespace bdx
135 : } // namespace chip
|