blob: eedeff319e41d31a72894df598cb5813e223a191 [file] [log] [blame]
/*
*
* Copyright (c) 2020 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 classes corresponding to CHIP Exchange Context.
*
*/
#pragma once
#include <lib/core/ReferenceCounted.h>
#include <messaging/ExchangeDelegate.h>
#include <support/BitFlags.h>
#include <support/DLLUtil.h>
#include <system/SystemTimer.h>
#include <transport/SecureSessionMgr.h>
namespace chip {
class ExchangeManager;
class ExchangeContext;
class ExchangeContextDeletor
{
public:
static void Release(ExchangeContext * obj);
};
/**
* @brief
* This class represents an ongoing conversation (ExchangeContext) between two or more nodes.
* It defines methods for encoding and communicating CHIP messages within an ExchangeContext
* over various transport mechanisms, for example, TCP, UDP, or CHIP Reliable Messaging.
*/
class DLL_EXPORT ExchangeContext : public ReferenceCounted<ExchangeContext, ExchangeContextDeletor, 0>
{
friend class ExchangeManager;
friend class ExchangeContextDeletor;
public:
enum
{
kSendFlag_ExpectResponse = 0x0001, // Used to indicate that a response is expected within a specified timeout.
kSendFlag_RetainBuffer = 0x0002, // Used to indicate that the message buffer should not be freed after sending.
};
/**
* Determine whether the context is the initiator of the exchange.
*
* @return Returns 'true' if it is the initiator, else 'false'.
*/
bool IsInitiator() const;
/**
* Determine whether a response is expected for messages sent over
* this exchange.
*
* @return Returns 'true' if response expected, else 'false'.
*/
bool IsResponseExpected() const;
/**
* Set whether a response is expected on this exchange.
*
* @param[in] inResponseExpected A Boolean indicating whether (true) or not
* (false) a response is expected on this
* exchange.
*/
void SetResponseExpected(bool inResponseExpected);
/**
* Send a CHIP message on this exchange.
*
* @param[in] protocolId The protocol identifier of the CHIP message to be sent.
*
* @param[in] msgType The message type of the corresponding protocol.
*
* @param[in] msgPayload A pointer to the PacketBuffer object holding the CHIP message.
*
* @param[in] sendFlags Flags set by the application for the CHIP message being sent.
*
* @param[in] msgCtxt A pointer to an application-specific context object to be associated
* with the message being sent.
* @retval #CHIP_ERROR_INVALID_ARGUMENT if an invalid argument was passed to this SendMessage API.
* @retval #CHIP_ERROR_SEND_THROTTLED if this exchange context has been throttled when using the
* CHIP reliable messaging protocol.
* @retval #CHIP_ERROR_WRONG_MSG_VERSION_FOR_EXCHANGE if there is a mismatch in the specific send operation and the
* CHIP message protocol version that is supported.
* @retval #CHIP_ERROR_NOT_CONNECTED if the context was associated with a connection that is now
* closed.
* @retval #CHIP_ERROR_INCORRECT_STATE if the state of the exchange context is incorrect.
* @retval #CHIP_NO_ERROR if the CHIP layer successfully sent the message down to the
* network layer.
*/
CHIP_ERROR SendMessage(uint16_t protocolId, uint8_t msgType, System::PacketBuffer * msgPayload, uint16_t sendFlags = 0,
void * msgCtxt = nullptr);
/**
* Handle a received CHIP message on this exchange.
*
* @param[in] packetHeader A reference to the PacketHeader object.
*
* @param[in] payloadHeader A reference to the PayloadHeader object.
*
* @param[in] msgBuf A handle to the PacketBuffer object holding the CHIP message.
*
* @retval #CHIP_ERROR_INVALID_ARGUMENT if an invalid argument was passed to this HandleMessage API.
* @retval #CHIP_ERROR_INCORRECT_STATE if the state of the exchange context is incorrect.
* @retval #CHIP_NO_ERROR if the CHIP layer successfully delivered the message up to the
* protocol layer.
*/
CHIP_ERROR HandleMessage(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
System::PacketBufferHandle msgBuf);
ExchangeDelegate * GetDelegate() const { return mDelegate; }
void SetDelegate(ExchangeDelegate * delegate) { mDelegate = delegate; }
ExchangeManager * GetExchangeMgr() const { return mExchangeMgr; }
uint64_t GetPeerNodeId() const { return mPeerNodeId; }
uint16_t GetExchangeId() const { return mExchangeId; }
/*
* In order to use reference counting (see refCount below) we use a hold/free paradigm where users of the exchange
* can hold onto it while it's out of their direct control to make sure it isn't closed before everyone's ready.
* A customized version of reference counting is used since there are some extra stuff to do within Release.
*/
void Close();
void Abort();
ExchangeContext * Alloc(ExchangeManager * em, uint16_t ExchangeId, uint64_t PeerNodeId, bool Initiator,
ExchangeDelegate * delegate);
void Free();
void Reset();
private:
enum class ExFlagValues : uint16_t
{
kFlagInitiator = 0x0001, // This context is the initiator of the exchange.
kFlagResponseExpected = 0x0002, // If a response is expected for a message that is being sent.
};
typedef uint32_t Timeout; // Type used to express the timeout in this ExchangeContext, in milliseconds
Timeout mResponseTimeout; // Maximum time to wait for response (in milliseconds); 0 disables response timeout.
ExchangeDelegate * mDelegate = nullptr;
ExchangeManager * mExchangeMgr = nullptr;
uint64_t mPeerNodeId; // Node ID of peer node.
uint16_t mExchangeId; // Assigned exchange ID.
BitFlags<uint16_t, ExFlagValues> mFlags; // Internal state flags
/**
* Search for an existing exchange that the message applies to.
*
* @param[in] packetHeader A reference to the PacketHeader object.
*
* @param[in] payloadHeader A reference to the PayloadHeader object.
*
* @retval true If a match is found.
* @retval false If a match is not found.
*/
bool MatchExchange(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader);
CHIP_ERROR StartResponseTimer();
void CancelResponseTimer();
static void HandleResponseTimeout(System::Layer * aSystemLayer, void * aAppState, System::Error aError);
void DoClose(bool clearRetransTable);
};
inline void ExchangeContextDeletor::Release(ExchangeContext * obj)
{
obj->Free();
}
} // namespace chip