Apply Upstream code (2021-03-15)
[platform/upstream/connectedhomeip.git] / src / messaging / ExchangeContext.h
1 /*
2  *
3  *    Copyright (c) 2020-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 /**
19  *    @file
20  *      This file defines the classes corresponding to CHIP Exchange Context.
21  *
22  */
23
24 #pragma once
25
26 #include <lib/core/ReferenceCounted.h>
27 #include <messaging/ExchangeACL.h>
28 #include <messaging/ExchangeDelegate.h>
29 #include <messaging/Flags.h>
30 #include <messaging/ReliableMessageContext.h>
31 #include <support/BitFlags.h>
32 #include <support/DLLUtil.h>
33 #include <system/SystemTimer.h>
34 #include <transport/SecureSessionMgr.h>
35
36 namespace chip {
37
38 constexpr uint16_t kMsgCounterChallengeSize = 8; // The size of the message counter synchronization request message.
39
40 namespace Messaging {
41
42 class ExchangeManager;
43 class ExchangeContext;
44
45 class ExchangeContextDeletor
46 {
47 public:
48     static void Release(ExchangeContext * obj);
49 };
50
51 /**
52  *  @brief
53  *    This class represents an ongoing conversation (ExchangeContext) between two or more nodes.
54  *    It defines methods for encoding and communicating CHIP messages within an ExchangeContext
55  *    over various transport mechanisms, for example, TCP, UDP, or CHIP Reliable Messaging.
56  */
57 class DLL_EXPORT ExchangeContext : public ReferenceCounted<ExchangeContext, ExchangeContextDeletor, 0>
58 {
59     friend class ExchangeManager;
60     friend class ExchangeContextDeletor;
61     friend class MessageCounterSyncMgr;
62
63 public:
64     typedef uint32_t Timeout; // Type used to express the timeout in this ExchangeContext, in milliseconds
65
66     /**
67      *  Determine whether the context is the initiator of the exchange.
68      *
69      *  @return Returns 'true' if it is the initiator, else 'false'.
70      */
71     bool IsInitiator() const;
72
73     /**
74      *  Determine whether a response is expected for messages sent over
75      *  this exchange.
76      *
77      *  @return Returns 'true' if response expected, else 'false'.
78      */
79     bool IsResponseExpected() const;
80
81     /**
82      *  Set whether a response is expected on this exchange.
83      *
84      *  @param[in]  inResponseExpected  A Boolean indicating whether (true) or not
85      *                                  (false) a response is expected on this
86      *                                  exchange.
87      */
88     void SetResponseExpected(bool inResponseExpected);
89
90     /**
91      *  Send a CHIP message on this exchange.
92      *
93      *  @param[in]    protocolId    The protocol identifier of the CHIP message to be sent.
94      *
95      *  @param[in]    msgType       The message type of the corresponding protocol.
96      *
97      *  @param[in]    msgPayload    A handle to the packet buffer holding the CHIP message.
98      *
99      *  @param[in]    sendFlags     Flags set by the application for the CHIP message being sent.
100      *
101      *  @retval  #CHIP_ERROR_INVALID_ARGUMENT               if an invalid argument was passed to this SendMessage API.
102      *  @retval  #CHIP_ERROR_WRONG_MSG_VERSION_FOR_EXCHANGE if there is a mismatch in the specific send operation and the
103      *                                                       CHIP message protocol version that is supported.
104      *  @retval  #CHIP_ERROR_NOT_CONNECTED                  if the context was associated with a connection that is now
105      *                                                       closed.
106      *  @retval  #CHIP_ERROR_INCORRECT_STATE                if the state of the exchange context is incorrect.
107      *  @retval  #CHIP_NO_ERROR                             if the CHIP layer successfully sent the message down to the
108      *                                                       network layer.
109      */
110     CHIP_ERROR SendMessage(uint16_t protocolId, uint8_t msgType, System::PacketBufferHandle msgPayload,
111                            const SendFlags & sendFlags);
112
113     /**
114      * A strongly-message-typed version of SendMessage.
115      */
116     template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
117     CHIP_ERROR SendMessage(MessageType msgType, System::PacketBufferHandle && msgPayload, const SendFlags & sendFlags)
118     {
119         static_assert(std::is_same<std::underlying_type_t<MessageType>, uint8_t>::value, "Enum is wrong size; cast is not safe");
120         return SendMessage(Protocols::MessageTypeTraits<MessageType>::ProtocolId, static_cast<uint8_t>(msgType),
121                            std::move(msgPayload), sendFlags);
122     }
123
124     /**
125      *  Handle a received CHIP message on this exchange.
126      *
127      *  @param[in]    packetHeader  A reference to the PacketHeader object.
128      *
129      *  @param[in]    payloadHeader A reference to the PayloadHeader object.
130      *
131      *  @param[in]    msgBuf        A handle to the packet buffer holding the CHIP message.
132      *
133      *  @retval  #CHIP_ERROR_INVALID_ARGUMENT               if an invalid argument was passed to this HandleMessage API.
134      *  @retval  #CHIP_ERROR_INCORRECT_STATE                if the state of the exchange context is incorrect.
135      *  @retval  #CHIP_NO_ERROR                             if the CHIP layer successfully delivered the message up to the
136      *                                                       protocol layer.
137      */
138     CHIP_ERROR HandleMessage(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader,
139                              System::PacketBufferHandle msgBuf);
140
141     ExchangeDelegate * GetDelegate() const { return mDelegate; }
142     void SetDelegate(ExchangeDelegate * delegate) { mDelegate = delegate; }
143     void SetReliableMessageDelegate(ReliableMessageDelegate * delegate) { mReliableMessageContext.SetDelegate(delegate); }
144
145     ExchangeManager * GetExchangeMgr() const { return mExchangeMgr; }
146
147     ReliableMessageContext * GetReliableMessageContext() { return &mReliableMessageContext; };
148
149     ExchangeACL * GetExchangeACL(Transport::AdminPairingTable & table)
150     {
151         if (mExchangeACL == nullptr)
152         {
153             Transport::AdminPairingInfo * admin = table.FindAdmin(mSecureSession.GetAdminId());
154             if (admin != nullptr)
155             {
156                 mExchangeACL = chip::Platform::New<CASEExchangeACL>(admin);
157             }
158         }
159
160         return mExchangeACL;
161     }
162
163     SecureSessionHandle GetSecureSession() { return mSecureSession; }
164
165     uint16_t GetExchangeId() const { return mExchangeId; }
166
167     void SetChallenge(const uint8_t * value) { memcpy(&mChallenge[0], value, kMsgCounterChallengeSize); }
168
169     const uint8_t * GetChallenge() const { return mChallenge; }
170
171     SecureSessionHandle GetSecureSessionHandle() const { return mSecureSession; }
172
173     /*
174      * In order to use reference counting (see refCount below) we use a hold/free paradigm where users of the exchange
175      * can hold onto it while it's out of their direct control to make sure it isn't closed before everyone's ready.
176      * A customized version of reference counting is used since there are some extra stuff to do within Release.
177      */
178     void Close();
179     void Abort();
180
181     ExchangeContext * Alloc(ExchangeManager * em, uint16_t ExchangeId, SecureSessionHandle session, bool Initiator,
182                             ExchangeDelegate * delegate);
183     void Free();
184     void Reset();
185
186     void SetResponseTimeout(Timeout timeout);
187
188 private:
189     enum class ExFlagValues : uint16_t
190     {
191         kFlagInitiator        = 0x0001, // This context is the initiator of the exchange.
192         kFlagResponseExpected = 0x0002, // If a response is expected for a message that is being sent.
193     };
194
195     Timeout mResponseTimeout; // Maximum time to wait for response (in milliseconds); 0 disables response timeout.
196     ReliableMessageContext mReliableMessageContext;
197     ExchangeDelegate * mDelegate   = nullptr;
198     ExchangeManager * mExchangeMgr = nullptr;
199     ExchangeACL * mExchangeACL     = nullptr;
200
201     SecureSessionHandle mSecureSession; // The connection state
202     uint16_t mExchangeId;               // Assigned exchange ID.
203
204     // [TODO: #4711]: this field need to be moved to appState object which implement 'exchange-specific' contextual
205     // actions with a delegate pattern.
206     uint8_t mChallenge[kMsgCounterChallengeSize]; // Challenge number to identify the sychronization request cryptographically.
207
208     BitFlags<ExFlagValues> mFlags; // Internal state flags
209
210     /**
211      *  Search for an existing exchange that the message applies to.
212      *
213      *  @param[in]    session       The secure session of the received message.
214      *
215      *  @param[in]    packetHeader  A reference to the PacketHeader object.
216      *
217      *  @param[in]    payloadHeader A reference to the PayloadHeader object.
218      *
219      *  @retval  true                                       If a match is found.
220      *  @retval  false                                      If a match is not found.
221      */
222     bool MatchExchange(SecureSessionHandle session, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader);
223
224     CHIP_ERROR StartResponseTimer();
225
226     /**
227      * A subset of SendMessage functionality that does not perform message
228      * counter sync for group keys.
229      */
230     CHIP_ERROR SendMessageImpl(uint16_t protocolId, uint8_t msgType, System::PacketBufferHandle msgBuf, const SendFlags & sendFlags,
231                                Transport::PeerConnectionState * state = nullptr);
232     void CancelResponseTimer();
233     static void HandleResponseTimeout(System::Layer * aSystemLayer, void * aAppState, System::Error aError);
234
235     void DoClose(bool clearRetransTable);
236 };
237
238 inline void ExchangeContextDeletor::Release(ExchangeContext * obj)
239 {
240     obj->Free();
241 }
242
243 } // namespace Messaging
244 } // namespace chip