-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
OTARequestor.h
197 lines (165 loc) · 7.67 KB
/
OTARequestor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file contains the declarations for the Matter OTA Requestor implementation and API.
* Applications implementing the OTA Requestor functionality must include this file.
*/
#pragma once
#include <app/CASESessionManager.h>
#include <protocols/bdx/BdxMessages.h>
#include "BDXDownloader.h"
#include "OTARequestorDriver.h"
#include "OTARequestorInterface.h"
namespace chip {
using namespace app::Clusters::OtaSoftwareUpdateProvider::Commands;
// This class implements all of the core logic of the OTA Requestor
class OTARequestor : public OTARequestorInterface
{
public:
// Various actions to take when OnConnected callback is called
enum OnConnectedAction
{
kQueryImage = 0,
kStartBDX,
};
OTARequestor() : mOnConnectedCallback(OnConnected, this), mOnConnectionFailureCallback(OnConnectionFailure, this) {}
// Application interface declarations -- start
// Application directs the Requestor to start the Image Query process
// and download the new image if available
void TriggerImmediateQuery();
// A setter for the delegate class pointer
void SetOtaRequestorDriver(OTARequestorDriver * driver) { mOtaRequestorDriver = driver; }
// TODO: this should really be OTADownloader, but right now OTARequestor has information that we need to initialize a
// BDXDownloader specifically.
// The BDXDownloader instance should already have the ImageProcessingDelegate set.
void SetBDXDownloader(chip::BDXDownloader * downloader) { mBdxDownloader = downloader; }
// Application directs the Requestor to abort any processing related to
// the image update
void AbortImageUpdate();
// Application interface declarations -- end
// Virtual functions from OTARequestorInterface start
// Handler for the AnnounceOTAProvider command
EmberAfStatus HandleAnnounceOTAProvider(
app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::DecodableType & commandData);
// Virtual functions from OTARequestorInterface -- end
/**
* Called to establish a session to mProviderNodeId on mProviderFabricIndex
*
* @param onConnectedAction The action to take once session to provider has been established
*/
void ConnectToProvider(OnConnectedAction onConnectedAction);
/**
* Called to indicate test mode. This is when the Requestor is used as a test tool and the the provider parameters are supplied
* explicitly.
*/
void TestModeSetProviderParameters(NodeId nodeId, FabricIndex fabIndex)
{
mProviderNodeId = nodeId;
mProviderFabricIndex = fabIndex;
}
private:
// TODO: the application should define this, along with initializing the BDXDownloader
// This class is purely for delivering messages and sending outgoing messages to/from the BDXDownloader.
class BDXMessenger : public chip::BDXDownloader::MessagingDelegate, public chip::Messaging::ExchangeDelegate
{
public:
CHIP_ERROR SendMessage(const chip::bdx::TransferSession::OutputEvent & event) override
{
ChipLogDetail(SoftwareUpdate, "BDX::SendMessage");
VerifyOrReturnError(mExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE);
chip::Messaging::SendFlags sendFlags;
if (event.msgTypeData.HasMessageType(chip::bdx::MessageType::ReceiveInit))
{
sendFlags.Set(chip::Messaging::SendMessageFlags::kFromInitiator);
}
if (!event.msgTypeData.HasMessageType(chip::bdx::MessageType::BlockAckEOF) &&
!event.msgTypeData.HasMessageType(chip::Protocols::SecureChannel::MsgType::StatusReport))
{
sendFlags.Set(chip::Messaging::SendMessageFlags::kExpectResponse);
}
ReturnErrorOnFailure(mExchangeCtx->SendMessage(event.msgTypeData.ProtocolId, event.msgTypeData.MessageType,
event.MsgData.Retain(), sendFlags));
return CHIP_NO_ERROR;
}
CHIP_ERROR OnMessageReceived(chip::Messaging::ExchangeContext * ec, const chip::PayloadHeader & payloadHeader,
chip::System::PacketBufferHandle && payload) override
{
if (mDownloader == nullptr)
{
ChipLogError(BDX, "BDXDownloader instance is null, can't pass message");
return CHIP_NO_ERROR;
}
else
{
mDownloader->OnMessageReceived(payloadHeader, payload.Retain());
}
// For a receiver using BDX Protocol, all received messages will require a response except for a StatusReport
if (!payloadHeader.HasMessageType(chip::Protocols::SecureChannel::MsgType::StatusReport))
{
ec->WillSendMessage();
}
return CHIP_NO_ERROR;
}
void OnResponseTimeout(chip::Messaging::ExchangeContext * ec) override
{
ChipLogError(BDX, "exchange timed out");
if (mDownloader != nullptr)
{
mDownloader->OnDownloadTimeout();
}
}
void Init(chip::BDXDownloader * downloader, chip::Messaging::ExchangeContext * ec)
{
mExchangeCtx = ec;
mDownloader = downloader;
}
private:
chip::Messaging::ExchangeContext * mExchangeCtx;
chip::BDXDownloader * mDownloader;
};
/**
* Setup CASESessionManager used to establish a session with the provider
*/
CHIP_ERROR SetupCASESessionManager(chip::FabricIndex fabricIndex);
/**
* Validate the URI and parse the BDX URI for various fields
*/
CHIP_ERROR ParseBdxUri(CharSpan uri, NodeId & nodeId, CharSpan & fileDesignator);
/**
* Session connection callbacks
*/
static void OnConnected(void * context, OperationalDeviceProxy * deviceProxy);
static void OnConnectionFailure(void * context, NodeId deviceId, CHIP_ERROR error);
Callback::Callback<OnDeviceConnected> mOnConnectedCallback;
Callback::Callback<OnDeviceConnectionFailure> mOnConnectionFailureCallback;
/**
* QueryImage callbacks
*/
static void OnQueryImageResponse(void * context, const QueryImageResponse::DecodableType & response);
static void OnQueryImageFailure(void * context, EmberAfStatus status);
OTARequestorDriver * mOtaRequestorDriver = nullptr;
NodeId mProviderNodeId = kUndefinedNodeId;
FabricIndex mProviderFabricIndex = kUndefinedFabricIndex;
uint32_t mOtaStartDelayMs = 0;
CASESessionManager * mCASESessionManager = nullptr;
OnConnectedAction mOnConnectedAction = kQueryImage;
Messaging::ExchangeContext * mExchangeCtx = nullptr;
BDXDownloader * mBdxDownloader = nullptr; // TODO: this should be OTADownloader
BDXMessenger mBdxMessenger; // TODO: ideally this is held by the application
};
} // namespace chip