blob: 2d6821ec1ef71147b816ad8c79e0e0c719d91ff1 [file] [log] [blame]
/*
*
* Copyright (c) 2021 Project CHIP Authors
*
* 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.
*/
/**
* @file
* This file defines the API classes for to CHIP Channel.
*
* Channel is a object to abstract all low layer dependencies of an
* exchange, including secure session, transport connection and network
* status.
*
* Channel is not connection. Channel can abstract both connection
* oriented and connectionless transports, It contains information to send
* and receive messages via exchanges. For example, when using
* connectionless transport, channel will contain peer address and session
* key; when using connection oriented transport, channel will contain
* connection handle and session key.
*
* Channel is not session. Session do persistent through cold reboot, but
* channel doesn't. Applications must re-establish channels after a cold
* reboot.
*
* Because channel is a local concept, peer device is not able aware of
* channel establishment events. Instead, peer device is able to aware
* session establishment events, connection establishment events for
* connection oriented transport and message received events for
* connectionless transport.
*/
#pragma once
#include <credentials/CHIPOperationalCredentials.h>
#include <inet/IPAddress.h>
#include <transport/raw/MessageHeader.h>
namespace chip {
namespace Messaging {
/**
* @brief
* The ChannelBuilder object provides information to build a Channel.
*
* ChannelBuilder can be used by application to provide information to
* request a channel to a peer. When a channel is requested via
* ExchangeManager::EstablishChannel, a ChannelHandle will be return to
* represent the state of the channel
*
* The ChannelBuilder object should be short-live and it is only used within
* ExchangeManager::EstablishChannel call, after the call its state will be
* copied into an internal object represented by ChannelHandle, then the
* ChannelBuilder can be safely released.
*/
class ChannelBuilder
{
public:
enum class TransportPreference
{
kConnectionless,
kPreferConnectionOriented, // will fallback to connectionless if TCP is not supported
kConnectionOriented, // will fail if TCP is not supported
kDefault = kConnectionless,
};
ChannelBuilder & SetPeerNodeId(NodeId peerNodeId)
{
mPeerNodeId = peerNodeId;
return *this;
}
NodeId GetPeerNodeId() const { return mPeerNodeId; }
ChannelBuilder & SetTransportPreference(TransportPreference preference)
{
mTransportPreference = preference;
return *this;
}
TransportPreference GetTransportPreference() const { return mTransportPreference; }
uint16_t GetPeerKeyID() const { return mCaseParameters.mPeerKeyId; }
ChannelBuilder & SetPeerKeyID(uint16_t keyId)
{
mCaseParameters.mPeerKeyId = keyId;
return *this;
}
Credentials::OperationalCredentialSet & GetOperationalCredentialSet() const
{
return *mCaseParameters.mOperationalCredentialSet;
}
ChannelBuilder & SetOperationalCredentialSet(Credentials::OperationalCredentialSet * operationalCredentialSet)
{
mCaseParameters.mOperationalCredentialSet = operationalCredentialSet;
return *this;
}
Optional<Inet::IPAddress> GetForcePeerAddress() const { return mForcePeerAddr; }
ChannelBuilder & SetForcePeerAddress(Inet::IPAddress peerAddr)
{
mForcePeerAddr.SetValue(peerAddr);
return *this;
}
private:
NodeId mPeerNodeId = kUndefinedNodeId;
TransportPreference mTransportPreference = TransportPreference::kDefault;
struct
{
uint16_t mPeerKeyId;
Credentials::OperationalCredentialSet * mOperationalCredentialSet;
} mCaseParameters;
Optional<Inet::IPAddress> mForcePeerAddr;
};
class ExchangeContext;
class ExchangeDelegate;
enum class ChannelState
{
kNone,
kPreparing,
kReady,
kClosed,
kFailed,
};
class ChannelContextHandleAssociation;
/**
* @brief
* ChannelHandle is a reference to a channel. An active ChannelHandle will
* keep the channel available and ready for use, such that a message can be
* sent immediately to the peer.
*
* The ChannelHandle controls the lifespan of the channel. When the handle
* is released, the channel will be flagged as pending close, and if there
* is no active exchange which is using the channel, the channel will be
* closed.
*
* The ChannelHandle will track channel status, and notify applications
* when the channel state changes via ChannelDelegate.
*/
class ChannelHandle
{
public:
explicit ChannelHandle(ChannelContextHandleAssociation * association = nullptr) : mAssociation(association) {}
~ChannelHandle() { Release(); }
// non copyable
ChannelHandle(const ChannelHandle &) = delete;
ChannelHandle & operator=(const ChannelHandle &) = delete;
// movable
ChannelHandle(ChannelHandle && that)
{
Release();
this->mAssociation = that.mAssociation;
that.mAssociation = nullptr;
}
ChannelHandle & operator=(ChannelHandle && that)
{
Release();
this->mAssociation = that.mAssociation;
that.mAssociation = nullptr;
return *this;
}
ChannelState GetState() const;
/*
* @brief
* Create a new exchange on the channel.
*
* @pre GetState() == ChannelState::kReady
*/
ExchangeContext * NewExchange(ExchangeDelegate * delegate);
void Release();
private:
ChannelContextHandleAssociation * mAssociation;
};
/**
* @brief
* Callback receiver interface of channels
*/
class ChannelDelegate
{
public:
virtual ~ChannelDelegate() {}
virtual void OnEstablished() = 0;
virtual void OnClosed() = 0;
virtual void OnFail(CHIP_ERROR err) = 0;
};
} // namespace Messaging
} // namespace chip