blob: 65c1bd1fca7d47d3c1f27662fff1a918c0faf021 [file] [log] [blame]
/*
*
* 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.
*/
#pragma once
#include <controller/CHIPDevice.h>
namespace chip {
namespace app {
namespace device {
/**
* This struct contains device specific parameters that are needed to establish a secure session. The
* pointers passed in are not owned by this object and should have a lifetime beyond this object.
*/
struct OperationalDeviceProxyInitParams
{
SessionManager * sessionManager = nullptr;
Messaging::ExchangeManager * exchangeMgr = nullptr;
SessionIDAllocator * idAllocator = nullptr;
FabricTable * fabricsTable = nullptr;
};
class OperationalDeviceProxy;
// TODO: https://github.com/project-chip/connectedhomeip/issues/10423 will provide a refactor of the `Device`
// class. When that happens, the type of the last param for this callback may change as the registrar of this
// callback would need to be able to associate the peer device with the cluster command being setn.
typedef void (*OnOperationalDeviceConnected)(void * context, OperationalDeviceProxy * operationalDeviceProxy);
typedef void (*OnOperationalDeviceConnectionFailure)(void * context, OperationalDeviceProxy * operationalDeviceProxy,
CHIP_ERROR error);
/**
* @class OperationalDeviceProxy
*
* @brief This is a device proxy class for any two devices on the operational network to establish a
* secure session with each other via CASE. To establish a secure session, the caller of this class
* must supply the node ID, fabric index, as well as other device specific parameters to the peer node
* it wants to communicate with.
*/
class DLL_EXPORT OperationalDeviceProxy
{
public:
virtual ~OperationalDeviceProxy() {}
OperationalDeviceProxy() :
mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
{}
/**
* @brief
* Initialize an operational device object with node ID, fabric index and other
* device specific parameters used to establish a secure session.
*
* @param[in] nodeId Node ID of the device in which the secure session is established for
* @param[in] fabricIndex Fabric index of the device in which the secure session is established for
* @param[in] initParams Device specific parameters used in establishing the secure session
*/
void Init(NodeId nodeId, FabricIndex fabricIndex, OperationalDeviceProxyInitParams initParams)
{
VerifyOrReturn(initParams.sessionManager != nullptr);
VerifyOrReturn(initParams.exchangeMgr != nullptr);
VerifyOrReturn(initParams.idAllocator != nullptr);
VerifyOrReturn(initParams.fabricsTable != nullptr);
mNodeId = nodeId;
mFabricIndex = fabricIndex;
mInitParams = initParams;
}
/**
* @brief
* Establish a secure session with the device via CASE.
*
* On establishing the session, the callback function `onConnection` will be called. If the
* session setup fails, `onFailure` will be called.
*
* If the session already exists, `onConnection` will be called immediately.
*
* @param[in] onConnection Callback to call when secure session successfully established
* @param[in] onFailure Callback to call when secure session fails to be established
*/
CHIP_ERROR Connect(Callback::Callback<OnOperationalDeviceConnected> * onConnection,
Callback::Callback<OnOperationalDeviceConnectionFailure> * onFailure);
/**
* @brief
* Update address of the device. The address is used as part of secure session establishment
* and therefore, must be updated before a secure session is established.
*
* @param[in] address Address of the device in which the secure session is established for
*/
// TODO: After a requested CHIP node ID has been successfully resolved, call this to update
CHIP_ERROR UpdateAddress(const Transport::PeerAddress & address);
/**
* @brief
* Called when a secure session is being established
*
* @param[in] session The handle to the secure session
*/
void OnNewConnection(SessionHandle session);
/**
* @brief
* Called when a secure session is closing
*
* @param[in] session The handle to the secure session
*/
void OnConnectionExpired(SessionHandle session);
chip::Controller::Device & GetDevice() { return mDevice; }
private:
enum class State
{
Uninitialized,
Initialized,
Connecting,
SecureConnected,
};
/* Node ID assigned to the device */
NodeId mNodeId = kUndefinedNodeId;
/* Fabric index of the device */
FabricIndex mFabricIndex = kUndefinedFabricIndex;
/* Device specific parameters needed to establish a secure session */
OperationalDeviceProxyInitParams mInitParams;
/* Address used to communicate with the device */
Transport::PeerAddress mAddress = Transport::PeerAddress::UDP(Inet::IPAddress::Any);
/* Current state of the proxy */
State mState = State::Uninitialized;
/* Tracker of callbacks for the device */
Callback::CallbackDeque mConnectionSuccess;
Callback::CallbackDeque mConnectionFailure;
// TODO: https://github.com/project-chip/connectedhomeip/issues/10423 will provide a refactor of the `Device`
// class. When that happens, this class will no longer act as a wrapper to the `Device` class. This class
// should not need to hold a Device class object.
Controller::Device mDevice;
/**
* ----- Member functions -----
*/
void EnqueueConnectionCallbacks(Callback::Callback<OnOperationalDeviceConnected> * onConnection,
Callback::Callback<OnOperationalDeviceConnectionFailure> * onFailure);
void DequeueConnectionSuccessCallbacks(bool executeCallback);
void DequeueConnectionFailureCallbacks(CHIP_ERROR error, bool executeCallback);
/**
* ----- Wrapper callbacks for Device class -----
*/
// TODO: https://github.com/project-chip/connectedhomeip/issues/10423 will provide a refactor of the `Device`
// class. When that happens, these callbacks are no longer needed. They are currently being used to forward
// callbacks from the `Device` class to the users of the `OperationalDeviceProxy` class. Once the
// `OperationalDeviceProxy` class is no longer a wrapper to the `Device` class, the former will no longer
// need to register for the following callbacks to the `Device` class.
static void OnDeviceConnectedFn(void * context, chip::Controller::Device * device);
static void OnDeviceConnectionFailureFn(void * context, NodeId deviceId, CHIP_ERROR error);
chip::Callback::Callback<chip::Controller::OnDeviceConnected> mOnDeviceConnectedCallback;
chip::Callback::Callback<chip::Controller::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
};
} // namespace device
} // namespace app
} // namespace chip