Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020 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 Delegate.
21 : *
22 : */
23 :
24 : #pragma once
25 :
26 : #include <lib/support/CHIPMem.h>
27 : #include <messaging/ApplicationExchangeDispatch.h>
28 : #include <messaging/ExchangeMessageDispatch.h>
29 : #include <system/SystemPacketBuffer.h>
30 : #include <transport/SessionManager.h>
31 : #include <transport/raw/MessageHeader.h>
32 :
33 : namespace chip {
34 : namespace Messaging {
35 :
36 : class ExchangeContext;
37 :
38 : /**
39 : * @brief
40 : * This class provides a skeleton for the callback functions. The functions will be
41 : * called by ExchangeContext object on specific events. If the user of ExchangeContext
42 : * is interested in receiving these callbacks, they can specialize this class and handle
43 : * each trigger in their implementation of this class.
44 : *
45 : * For consumers who use an ExchangeContext to send/receive protocol messages, there are specific
46 : * expectations around who manages the exchange w.r.t clean-up and destruction:
47 : * 1. When you allocate an exchange, you own the exchange. Until you send a message successfully, it's on you
48 : * to release that ownership by calling Close or Abort on the exchange.
49 : *
50 : * 2. If you send a message successfully that doesn't require a response, the ownership transfers to
51 : * the ExchangeMgr, and it will close the exchange for you automatically.
52 : *
53 : * 3. If you send a message successfully that does require a response and desire to close it before
54 : * you get any notifications on that exchange from the ExchangeMgr, you should call Close or Abort on that exchange.
55 : *
56 : * 4. On reception of a message on an exchange, the ownership transfers to the OnMessageReceived callee.
57 : * If you return from OnMessageReceived and no messages were sent on that exchange, the exchange will transfer back
58 : * to the ExchangeMgr and it will automatically close it.
59 : *
60 : * 5. If you call WillSendMessage on the exchange in OnMessageReceived indicating a desire to send a message later
61 : * on the exchange, then the exchange remains with you, and it's your responsibility to either send a message on it,
62 : * or Close/Abort if you no longer wish to have the exchange around.
63 : *
64 : * 6. If you get a call to OnExchangeClosing, you should null out your reference to the exchange UNLESS you still
65 : * hold ownership of the exchange (i.e due to a prior call to WillSendMessage). In that case, you should call Abort/Close
66 : * whenever you're done with using the exchange. Those calls can be made synchronously within the OnExchangeClosing
67 : * callback.
68 : *
69 : * 7. If you get a call to OnResponseTimeout, you should null out your reference to the exchange since the exchange layer
70 : * owns the exchange and will handle releasing the ref later. A call to OnExchangeClosing will follow after.
71 : *
72 : */
73 : class DLL_EXPORT ExchangeDelegate
74 : {
75 : public:
76 1375 : virtual ~ExchangeDelegate() {}
77 :
78 : /**
79 : * @brief
80 : * This function is the protocol callback for handling a received CHIP
81 : * message.
82 : *
83 : * After calling this method an exchange will close itself unless one of
84 : * two things happens:
85 : *
86 : * 1) A call to SendMessage on the exchange with the kExpectResponse flag
87 : * set.
88 : * 2) A call to WillSendMessage on the exchange.
89 : *
90 : * Consumers that don't do one of those things MUST NOT retain a pointer
91 : * to the exchange.
92 : *
93 : * @param[in] ec A pointer to the ExchangeContext object.
94 : * @param[in] payloadHeader A reference to the PayloadHeader object.
95 : * @param[in] payload A handle to the PacketBuffer object holding the message payload.
96 : */
97 : virtual CHIP_ERROR OnMessageReceived(ExchangeContext * ec, const PayloadHeader & payloadHeader,
98 : System::PacketBufferHandle && payload) = 0;
99 :
100 : /**
101 : * @brief
102 : * This function is the protocol callback to invoke when the timeout for the receipt
103 : * of a response message has expired.
104 : *
105 : * After calling this method an exchange will close itself unless one of
106 : * two things happens:
107 : *
108 : * 1) A call to SendMessage on the exchange with the kExpectResponse flag
109 : * set.
110 : * 2) A call to WillSendMessage on the exchange.
111 : *
112 : * Consumers that don't do one of those things MUST NOT retain a pointer
113 : * to the exchange.
114 : *
115 : * @param[in] ec A pointer to the ExchangeContext object.
116 : */
117 : virtual void OnResponseTimeout(ExchangeContext * ec) = 0;
118 :
119 : /**
120 : * @brief
121 : * This function is the protocol callback to invoke when the associated
122 : * exchange context is being closed.
123 : *
124 : * If the exchange was in a state where it was expecting a message to be
125 : * sent due to an earlier WillSendMessage call or because the exchange has
126 : * just been created as an initiator, the consumer is holding a reference
127 : * to the exchange and it's the consumer's responsibility to call
128 : * Release() on the exchange at some point. The usual way this happens is
129 : * that the consumer tries to send its message, that fails, and the
130 : * consumer calls Close() on the exchange. Calling Close() after an
131 : * OnExchangeClosing() notification is allowed in this situation.
132 : *
133 : * @param[in] ec A pointer to the ExchangeContext object.
134 : */
135 313 : virtual void OnExchangeClosing(ExchangeContext * ec) {}
136 :
137 398 : virtual ExchangeMessageDispatch & GetMessageDispatch() { return ApplicationExchangeDispatch::Instance(); }
138 : };
139 :
140 : /**
141 : * @brief
142 : * This class handles unsolicited messages. The implementation can select an exchange delegate to use based on the payload header
143 : * of the incoming message or its session.
144 : */
145 : class DLL_EXPORT UnsolicitedMessageHandler
146 : {
147 : public:
148 309 : virtual ~UnsolicitedMessageHandler() {}
149 :
150 : /**
151 : * @brief
152 : * This function handles an unsolicited CHIP message.
153 : *
154 : * If the implementation returns CHIP_NO_ERROR, it is expected to set newDelegate to the delegate to use for the exchange
155 : * handling the message. The message layer will handle creating the exchange with this delegate.
156 : *
157 : * If the implementation returns an error, message processing will be aborted for this message.
158 : *
159 : * @param[in] payloadHeader A reference to the PayloadHeader object for the unsolicited message. The protocol and message
160 : * type of this header match the UnsolicitedMessageHandler.
161 : * @param[in] session A reference to the session where unsolicited message was received.
162 : * @param[out] newDelegate A new exchange delegate to be used by the new exchange created to handle the message.
163 : */
164 194 : virtual CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, const SessionHandle & session,
165 : ExchangeDelegate *& newDelegate)
166 : {
167 194 : return OnUnsolicitedMessageReceived(payloadHeader, newDelegate);
168 : }
169 :
170 0 : virtual CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate)
171 : {
172 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
173 : }
174 :
175 : /**
176 : * @brief
177 : * This function is called when OnUnsolicitedMessageReceived successfully returns a new delegate, but the session manager
178 : * fails to assign the delegate to a new exchange. It can be used to free the delegate as needed.
179 : *
180 : * Once an exchange is created with the delegate, the OnExchangeClosing notification can be used to free the delegate as
181 : * needed.
182 : *
183 : * @param[in] delegate The exchange delegate to be released.
184 : */
185 0 : virtual void OnExchangeCreationFailed(ExchangeDelegate * delegate) {}
186 : };
187 :
188 : } // namespace Messaging
189 : } // namespace chip
|