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 : CHIP_ERROR TransferFacilitator::OnMessageReceived(chip::Messaging::ExchangeContext * ec, const chip::PayloadHeader & payloadHeader,
36 : chip::System::PacketBufferHandle && payload)
37 : {
38 0 : if (mExchangeCtx == nullptr)
39 : {
40 0 : mExchangeCtx = ec;
41 : }
42 :
43 0 : ChipLogDetail(BDX, "%s: message " ChipLogFormatMessageType " protocol " ChipLogFormatProtocolId, __FUNCTION__,
44 : payloadHeader.GetMessageType(), ChipLogValueProtocolId(payloadHeader.GetProtocolID()));
45 : CHIP_ERROR err =
46 0 : mTransfer.HandleMessageReceived(payloadHeader, std::move(payload), System::SystemClock().GetMonotonicTimestamp());
47 0 : if (err != CHIP_NO_ERROR)
48 : {
49 0 : ChipLogError(BDX, "failed to handle message: %" CHIP_ERROR_FORMAT, err.Format());
50 : }
51 :
52 : // Almost every BDX message will follow up with a response on the exchange. Even messages that might signify the end of a
53 : // transfer could necessitate a response if they are received at the wrong time.
54 : // For this reason, it is left up to the application logic to call ExchangeContext::Close() when it has determined that the
55 : // transfer is finished.
56 0 : mExchangeCtx->WillSendMessage();
57 :
58 0 : return err;
59 : }
60 :
61 0 : void TransferFacilitator::OnResponseTimeout(Messaging::ExchangeContext * ec)
62 : {
63 0 : ChipLogError(BDX, "%s, ec: " ChipLogFormatExchange, __FUNCTION__, ChipLogValueExchange(ec));
64 0 : mExchangeCtx = nullptr;
65 0 : mTransfer.Reset();
66 0 : }
67 :
68 0 : void TransferFacilitator::PollTimerHandler(chip::System::Layer * systemLayer, void * appState)
69 : {
70 0 : VerifyOrReturn(appState != nullptr);
71 0 : static_cast<TransferFacilitator *>(appState)->PollForOutput();
72 : }
73 :
74 0 : void TransferFacilitator::PollForOutput()
75 : {
76 0 : TransferSession::OutputEvent outEvent;
77 0 : mTransfer.PollOutput(outEvent, System::SystemClock().GetMonotonicTimestamp());
78 0 : HandleTransferSessionOutput(outEvent);
79 :
80 0 : VerifyOrReturn(mSystemLayer != nullptr, ChipLogError(BDX, "%s mSystemLayer is null", __FUNCTION__));
81 0 : if (!mStopPolling)
82 : {
83 0 : mSystemLayer->StartTimer(mPollFreq, PollTimerHandler, this);
84 : }
85 : else
86 : {
87 0 : mSystemLayer->CancelTimer(PollTimerHandler, this);
88 0 : mStopPolling = false;
89 : }
90 0 : }
91 :
92 0 : void TransferFacilitator::ScheduleImmediatePoll()
93 : {
94 0 : VerifyOrReturn(mSystemLayer != nullptr, ChipLogError(BDX, "%s mSystemLayer is null", __FUNCTION__));
95 0 : mSystemLayer->StartTimer(System::Clock::Milliseconds32(kImmediatePollDelay), PollTimerHandler, this);
96 : }
97 :
98 0 : CHIP_ERROR Responder::PrepareForTransfer(System::Layer * layer, TransferRole role, BitFlags<TransferControlFlags> xferControlOpts,
99 : uint16_t maxBlockSize, System::Clock::Timeout timeout, System::Clock::Timeout pollFreq)
100 : {
101 0 : VerifyOrReturnError(layer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
102 :
103 0 : mPollFreq = pollFreq;
104 0 : mSystemLayer = layer;
105 :
106 0 : ReturnErrorOnFailure(mTransfer.WaitForTransfer(role, xferControlOpts, maxBlockSize, timeout));
107 :
108 0 : ChipLogProgress(BDX, "Start polling for messages");
109 0 : mStopPolling = false;
110 0 : mSystemLayer->StartTimer(mPollFreq, PollTimerHandler, this);
111 0 : return CHIP_NO_ERROR;
112 : }
113 :
114 0 : void Responder::ResetTransfer()
115 : {
116 0 : mTransfer.Reset();
117 0 : ChipLogProgress(BDX, "Stop polling for messages");
118 0 : mStopPolling = true;
119 0 : }
120 :
121 0 : CHIP_ERROR Initiator::InitiateTransfer(System::Layer * layer, TransferRole role, const TransferSession::TransferInitData & initData,
122 : System::Clock::Timeout timeout, System::Clock::Timeout pollFreq)
123 : {
124 0 : VerifyOrReturnError(layer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
125 :
126 0 : mPollFreq = pollFreq;
127 0 : mSystemLayer = layer;
128 :
129 0 : ReturnErrorOnFailure(mTransfer.StartTransfer(role, initData, timeout));
130 :
131 0 : mSystemLayer->StartTimer(mPollFreq, PollTimerHandler, this);
132 0 : return CHIP_NO_ERROR;
133 : }
134 :
135 0 : void Initiator::ResetTransfer()
136 : {
137 0 : mTransfer.Reset();
138 0 : ChipLogProgress(BDX, "Stop polling for messages");
139 0 : mStopPolling = true;
140 0 : }
141 :
142 : } // namespace bdx
143 : } // namespace chip
|