Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #pragma once
20 :
21 : #include <app/CASEClientPool.h>
22 : #include <app/OperationalSessionSetup.h>
23 : #include <app/OperationalSessionSetupPool.h>
24 : #include <lib/address_resolve/AddressResolve.h>
25 : #include <lib/core/CHIPConfig.h>
26 : #include <lib/core/CHIPCore.h>
27 : #include <lib/support/Pool.h>
28 : #include <platform/CHIPDeviceLayer.h>
29 : #include <transport/SessionDelegate.h>
30 : #include <transport/SessionManager.h>
31 : #include <transport/SessionUpdateDelegate.h>
32 :
33 : namespace chip {
34 :
35 : struct CASESessionManagerConfig
36 : {
37 : CASEClientInitParams sessionInitParams;
38 : CASEClientPoolDelegate * clientPool = nullptr;
39 : OperationalSessionSetupPoolDelegate * sessionSetupPool = nullptr;
40 : };
41 :
42 : /**
43 : * This class provides the following
44 : * 1. Manage a pool of operational device proxy objects for peer nodes that have active message exchange with the local node.
45 : * 2. The pool contains atmost one device proxy object for a given peer node.
46 : * 3. API to lookup an existing proxy object, or allocate a new one by triggering session establishment with the peer node.
47 : * 4. During session establishment, trigger node ID resolution (if needed), and update the DNS-SD cache (if resolution is
48 : * successful)
49 : */
50 : class CASESessionManager : public OperationalSessionReleaseDelegate, public SessionUpdateDelegate
51 : {
52 : public:
53 : // Grants tests access to the private mConfig so they can install a
54 : // session-setup pool without standing up a full CASE stack, in order to
55 : // exercise ReleaseSession(peerId) behavior directly.
56 : friend class TestCASESessionManagerAccess;
57 :
58 158 : CASESessionManager() = default;
59 158 : virtual ~CASESessionManager()
60 158 : {
61 316 : if (mConfig.sessionInitParams.Validate() == CHIP_NO_ERROR)
62 : {
63 1 : mConfig.sessionInitParams.exchangeMgr->GetReliableMessageMgr()->RegisterSessionUpdateDelegate(nullptr);
64 : }
65 158 : }
66 :
67 : CHIP_ERROR Init(chip::System::Layer * systemLayer, const CASESessionManagerConfig & params);
68 : void Shutdown();
69 :
70 : /**
71 : * Find an existing session for the given node ID, or trigger a new session
72 : * request with optional DNS-SD fallback support.
73 : *
74 : * The caller can optionally provide `onConnection` and `onFailure` callback
75 : * objects. If provided, these will be used to inform the caller about
76 : * successful or failed connection establishment.
77 : *
78 : * If the connection is already established, the `onConnection` callback
79 : * will be immediately called, before FindOrEstablishSession returns.
80 : *
81 : * The `onFailure` callback may be called before the FindOrEstablishSession
82 : * call returns, for error cases that are detected synchronously.
83 : *
84 : * attemptCount can be set to a value greater than 1 to automatically make at least
85 : * attemptCount session establishment attempts until session setup is successful.
86 : */
87 : void FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
88 : Callback::Callback<OnDeviceConnectionFailure> * onFailure,
89 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
90 : uint8_t attemptCount = 1, Callback::Callback<OnDeviceConnectionRetry> * onRetry = nullptr,
91 : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
92 : TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload,
93 : const Optional<AddressResolve::ResolveResult> & fallbackResolveResult = NullOptional);
94 :
95 : /**
96 : * Find an existing session for the given node ID or trigger a new session request.
97 : *
98 : * The caller can optionally provide `onConnection` and `onSetupFailure`
99 : * callback objects. If provided, these will be used to inform the caller about successful or
100 : * failed connection establishment.
101 : *
102 : * If the connection is already established, the `onConnection` callback will be immediately called,
103 : * before `FindOrEstablishSession` returns.
104 : *
105 : * The `onSetupFailure` callback may be called before the `FindOrEstablishSession`
106 : * call returns, for error cases that are detected synchronously.
107 : *
108 : * The `attemptCount` parameter can be set to a value greater than 1 to automatically make
109 : * at least attemptCount session establishment attempts until session setup is successful.
110 : *
111 : * @param peerId The node ID to find or establish a session with.
112 : * @param onConnection A callback to be called upon successful connection establishment.
113 : * @param onSetupFailure A callback to be called upon an extended device connection failure.
114 : * @param attemptCount The number of attempts to make at establishing a session. If set to a number larger than 1,
115 : * a session setup failure will lead to a retry, with at least attemptCount total attempts.
116 : * @param onRetry A callback to be called on a retry attempt (enabled by a config flag).
117 : * @param transportPayloadCapability An indicator of what payload types the session needs to be able to transport.
118 : */
119 : void FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
120 : Callback::Callback<OperationalSessionSetup::OnSetupFailure> * onSetupFailure,
121 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
122 : uint8_t attemptCount = 1, Callback::Callback<OnDeviceConnectionRetry> * onRetry = nullptr,
123 : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
124 : TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload);
125 :
126 : /**
127 : * Find an existing session for the given node ID or trigger a new session request.
128 : *
129 : * The caller can optionally provide `onConnection`
130 : * callback objects. If provided, these will be used to inform the caller about successful connection establishment.
131 : *
132 : * If the connection is already established, the `onConnection` callback will be immediately called,
133 : * before `FindOrEstablishSession` returns.
134 : *
135 : * The `attemptCount` parameter can be set to a value greater than 1 to automatically make
136 : * at least attemptCount session establishment attempts until session setup is successful.
137 : *
138 : * This function allows passing 'nullptr' for the error handler to compile, which is useful in scenarios where error
139 : * handling is not needed.
140 : *
141 : * @param peerId The node ID to find or establish a session with.
142 : * @param onConnection A callback to be called upon successful connection establishment.
143 : * @param attemptCount The number of attempts to make at establishing a session. If set to a number larger than 1,
144 : * a session setup failure will lead to a retry, with at least attemptCount total attempts.
145 : * @param onRetry A callback to be called on a retry attempt (enabled by a config flag).
146 : * @param transportPayloadCapability An indicator of what payload types the session needs to be able to transport.
147 : */
148 : void FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection, std::nullptr_t,
149 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
150 : uint8_t attemptCount = 1, Callback::Callback<OnDeviceConnectionRetry> * onRetry = nullptr,
151 : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
152 : TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload);
153 :
154 : /**
155 : * Find an existing session for the given node ID or trigger a new session request.
156 : *
157 : * The caller can optionally provide `onConnection`
158 : * callback objects. If provided, these will be used to inform the caller about successful connection establishment.
159 : *
160 : * If the connection is already established, the `onConnection` callback will be immediately called,
161 : * before `FindOrEstablishSession` returns.
162 : *
163 : * The `onFailure` callback may be called before the FindOrEstablishSession
164 : * call returns, for error cases that are detected synchronously.
165 : *
166 : * @note This API uses default values for automatic CASE retries, if enabled.
167 : *
168 : * @param peerId The node ID to find or establish a session with.
169 : * @param onConnection A callback to be called upon successful connection establishment.
170 : * @param onSetupFailure A callback to be called upon an extended device connection failure.
171 : * @param transportPayloadCapability An indicator of what payload types the session needs to be able to transport.
172 : */
173 : void FindOrEstablishSession(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
174 : Callback::Callback<OnDeviceConnectionFailure> * onFailure,
175 : TransportPayloadCapability transportPayloadCapability);
176 :
177 : void ReleaseSession(const ScopedNodeId & peerId);
178 : void ReleaseSessionsForFabric(FabricIndex fabricIndex);
179 :
180 : void ReleaseAllSessions();
181 :
182 : /**
183 : * This API returns the address for the given node ID.
184 : * If the CASESessionManager is configured with a DNS-SD cache, the cache is looked up
185 : * for the node ID.
186 : * If the DNS-SD cache is not available, the CASESessionManager looks up the list for
187 : * an ongoing session with the peer node. If the session doesn't exist, the API will return
188 : * `CHIP_ERROR_NOT_CONNECTED` error.
189 : */
190 : CHIP_ERROR GetPeerAddress(const ScopedNodeId & peerId, Transport::PeerAddress & addr,
191 : TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload);
192 :
193 : //////////// OperationalSessionReleaseDelegate Implementation ///////////////
194 : void ReleaseSession(OperationalSessionSetup * device) override;
195 :
196 : //////////// SessionUpdateDelegate Implementation ///////////////
197 : void UpdatePeerAddress(ScopedNodeId peerId) override;
198 :
199 : private:
200 : OperationalSessionSetup * FindExistingSessionSetup(const ScopedNodeId & peerId, bool forAddressUpdate = false) const;
201 :
202 : Optional<SessionHandle> FindExistingSession(
203 : const ScopedNodeId & peerId,
204 : const TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload) const;
205 :
206 : void FindOrEstablishSessionHelper(const ScopedNodeId & peerId, Callback::Callback<OnDeviceConnected> * onConnection,
207 : Callback::Callback<OnDeviceConnectionFailure> * onFailure,
208 : Callback::Callback<OperationalSessionSetup::OnSetupFailure> * onSetupFailure,
209 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
210 : uint8_t attemptCount, Callback::Callback<OnDeviceConnectionRetry> * onRetry,
211 : #endif
212 : TransportPayloadCapability transportPayloadCapability,
213 : const Optional<AddressResolve::ResolveResult> & fallbackResolveResult = NullOptional);
214 :
215 : CASESessionManagerConfig mConfig;
216 : };
217 :
218 : } // namespace chip
|