Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2020-2021 Project CHIP Authors 4 : * Copyright (c) 2016-2017 Nest Labs, Inc. 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 : /** 20 : * @file 21 : * This file contains declarations of the 22 : * chip::System::Layer class and its related types, data and 23 : * functions. 24 : */ 25 : 26 : #pragma once 27 : 28 : // Include configuration headers 29 : #include <system/SystemConfig.h> 30 : 31 : #include <lib/core/CHIPCallback.h> 32 : 33 : #include <lib/support/CodeUtils.h> 34 : #include <lib/support/DLLUtil.h> 35 : #include <lib/support/LambdaBridge.h> 36 : #include <system/SystemClock.h> 37 : #include <system/SystemError.h> 38 : #include <system/SystemEvent.h> 39 : 40 : #if CHIP_SYSTEM_CONFIG_USE_SOCKETS 41 : #include <system/SocketEvents.h> 42 : #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS 43 : 44 : #if CHIP_SYSTEM_CONFIG_USE_DISPATCH 45 : #include <dispatch/dispatch.h> 46 : #elif CHIP_SYSTEM_CONFIG_USE_LIBEV 47 : #include <ev.h> 48 : #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV 49 : 50 : #include <utility> 51 : 52 : namespace chip { 53 : namespace System { 54 : 55 : class Layer; 56 : using TimerCompleteCallback = void (*)(Layer * aLayer, void * appState); 57 : 58 : /** 59 : * This provides access to timers according to the configured event handling model. 60 : * 61 : * The abstract class hierarchy is: 62 : * - Layer: Core timer methods. 63 : * - LayerFreeRTOS: Adds methods specific to CHIP_SYSTEM_CONFIG_USING_LWIP and CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT. 64 : * - LayerSockets: Adds I/O event methods specific to CHIP_SYSTEM_CONFIG_USING_SOCKETS. 65 : * - LayerSocketsLoop: Adds methods for event-loop-based implementations. 66 : * 67 : * Threading notes: 68 : * 69 : * The SDK is not generally thread safe. System::Layer methods should only be called from 70 : * a single context, or otherwise externally synchronized. For platforms that use a CHIP 71 : * event loop thread, timer callbacks are invoked on that thread; for platforms that use 72 : * a CHIP lock, the lock is held. 73 : */ 74 : class DLL_EXPORT Layer 75 : { 76 : public: 77 : Layer() = default; 78 0 : virtual ~Layer() = default; 79 : 80 : /** 81 : * Initialize the Layer. 82 : */ 83 : virtual CHIP_ERROR Init() = 0; 84 : 85 : /** 86 : * Shut down the Layer. 87 : * 88 : * Some other layers hold pointers to System::Layer, so care must be taken 89 : * to ensure that they are not used after calling Shutdown(). 90 : */ 91 : virtual void Shutdown() = 0; 92 : 93 : /** 94 : * True if this Layer is initialized. No method on Layer or its abstract descendants, other than this and `Init()`, 95 : * may be called from general code unless this is true. (Individual Impls may have looser constraints internally.) 96 : */ 97 : virtual bool IsInitialized() const = 0; 98 : 99 : /** 100 : * @brief 101 : * This method starts a one-shot timer. This method must be called while in the Matter context (from 102 : * the Matter event loop, or while holding the Matter stack lock). 103 : * 104 : * @note 105 : * Only a single timer is allowed to be started with the same @a aComplete and @a aAppState 106 : * arguments. If called with @a aComplete and @a aAppState identical to an existing timer, 107 : * the currently-running timer will first be cancelled. 108 : * 109 : * @param[in] aDelay Time before this timer fires. 110 : * @param[in] aComplete A pointer to the function called when timer expires. 111 : * @param[in] aAppState A pointer to the application state object used when timer expires. 112 : * 113 : * @return CHIP_NO_ERROR On success. 114 : * @return CHIP_ERROR_NO_MEMORY If a timer cannot be allocated. 115 : * @return Other Value indicating timer failed to start. 116 : */ 117 : virtual CHIP_ERROR StartTimer(Clock::Timeout aDelay, TimerCompleteCallback aComplete, void * aAppState) = 0; 118 : 119 : /** 120 : * @brief 121 : * This method extends the timer expiry to the provided aDelay. This method must be called while in the Matter context 122 : * (from the Matter event loop, or while holding the Matter stack lock). 123 : * aDelay is not added to the Remaining time of the timer. The finish line is pushed back to aDelay. 124 : * 125 : * @note The goal of this method is that the timer remaining time cannot be shrunk and only extended to a new time 126 : * If the provided new Delay is smaller than the timer's remaining time, the timer is left untouched. 127 : * In the other case the method acts like StartTimer 128 : * 129 : * @param[in] aDelay Time before this timer fires. 130 : * @param[in] aComplete A pointer to the function called when timer expires. 131 : * @param[in] aAppState A pointer to the application state object used when timer expires. 132 : * 133 : * @return CHIP_NO_ERROR On success. 134 : * @return CHIP_ERROR_INVALID_ARGUMENT If the provided aDelay value is 0 135 : * @return CHIP_ERROR_NO_MEMORY If a timer cannot be allocated. 136 : * @return Other Value indicating timer failed to start. 137 : */ 138 : virtual CHIP_ERROR ExtendTimerTo(Clock::Timeout aDelay, TimerCompleteCallback aComplete, void * aAppState) = 0; 139 : 140 : /** 141 : * @brief 142 : * This method searches for the timer matching the provided parameters. 143 : * and returns whether it is still "running" and waiting to trigger or not. 144 : * 145 : * @param[in] onComplete A pointer to the function called when timer expires. 146 : * @param[in] appState A pointer to the application state object used when timer expires. 147 : * 148 : * @return True if there is a current timer set to call, at some point in the future, the provided onComplete callback 149 : * with the corresponding appState context. False otherwise. 150 : */ 151 : virtual bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) = 0; 152 : 153 : /** 154 : * @brief This method cancels a one-shot timer, started earlier through @p StartTimer(). This method must 155 : * be called while in the Matter context (from the Matter event loop, or while holding the Matter 156 : * stack lock). 157 : * 158 : * @note 159 : * The cancellation could fail silently if the timer specified by the combination of the callback 160 : * function and application state object couldn't be found. 161 : * 162 : * @param[in] aOnComplete A pointer to the callback function used in calling @p StartTimer(). 163 : * @param[in] aAppState A pointer to the application state object used in calling @p StartTimer(). 164 : * 165 : */ 166 : virtual void CancelTimer(TimerCompleteCallback aOnComplete, void * aAppState) = 0; 167 : 168 : /** 169 : * @brief 170 : * Schedules a function with a signature identical to `OnCompleteFunct` to be run as soon as possible in the Matter context. 171 : * This must only be called when already in the Matter context (from the Matter event loop, or while holding the Matter 172 : * stack lock). 173 : * 174 : * @param[in] aComplete A pointer to a callback function to be called when this timer fires. 175 : * @param[in] aAppState A pointer to an application state object to be passed to the callback function as argument. 176 : * 177 : * @retval CHIP_ERROR_INCORRECT_STATE If the System::Layer has not been initialized. 178 : * @retval CHIP_ERROR_NO_MEMORY If the SystemLayer cannot allocate a new timer. 179 : * @retval CHIP_NO_ERROR On success. 180 : */ 181 : virtual CHIP_ERROR ScheduleWork(TimerCompleteCallback aComplete, void * aAppState) = 0; 182 : 183 : /** 184 : * @brief 185 : * Schedules a lambda even to be run as soon as possible in the CHIP context. This function is not thread-safe, 186 : * it must be called with in the CHIP context 187 : * 188 : * @param[in] event A object encapsulate the context of a lambda 189 : * 190 : * @retval CHIP_NO_ERROR On success. 191 : * @retval other Platform-specific errors generated indicating the reason for failure. 192 : */ 193 : CHIP_ERROR ScheduleLambdaBridge(LambdaBridge && event); 194 : 195 : /** 196 : * @brief 197 : * Schedules a lambda object to be run as soon as possible in the CHIP context. This function is not thread-safe, 198 : * it must be called with in the CHIP context 199 : */ 200 : template <typename Lambda> 201 : CHIP_ERROR ScheduleLambda(const Lambda & lambda) 202 : { 203 : LambdaBridge bridge; 204 : bridge.Initialize(lambda); 205 : return ScheduleLambdaBridge(std::move(bridge)); 206 : } 207 : 208 : private: 209 : // Copy and assignment NOT DEFINED 210 : Layer(const Layer &) = delete; 211 : Layer & operator=(const Layer &) = delete; 212 : }; 213 : 214 : #if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT 215 : 216 : class LayerFreeRTOS : public Layer 217 : { 218 : }; 219 : 220 : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP 221 : 222 : #if CHIP_SYSTEM_CONFIG_USE_SOCKETS 223 : 224 : class LayerSockets : public Layer 225 : { 226 : public: 227 : /** 228 : * Initialize watching for events on a file descriptor. 229 : * 230 : * Returns an opaque token through @a tokenOut that must be passed to subsequent operations for this file descriptor. 231 : * StopWatchingSocket() must be called before closing the file descriptor. 232 : */ 233 : virtual CHIP_ERROR StartWatchingSocket(int fd, SocketWatchToken * tokenOut) = 0; 234 : 235 : /** 236 : * Register a callback function. 237 : * 238 : * The callback will be invoked (with the CHIP stack lock held) when requested event(s) are ready. 239 : */ 240 : virtual CHIP_ERROR SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data) = 0; 241 : 242 : /** 243 : * Request a callback when the associated file descriptor is readable. 244 : */ 245 : virtual CHIP_ERROR RequestCallbackOnPendingRead(SocketWatchToken token) = 0; 246 : 247 : /** 248 : * Request a callback when the associated file descriptor is writable. 249 : */ 250 : virtual CHIP_ERROR RequestCallbackOnPendingWrite(SocketWatchToken token) = 0; 251 : 252 : /** 253 : * Cancel a request for a callback when the associated file descriptor is readable. 254 : */ 255 : virtual CHIP_ERROR ClearCallbackOnPendingRead(SocketWatchToken token) = 0; 256 : 257 : /** 258 : * Cancel a request for a callback when the associated file descriptor is writable. 259 : */ 260 : virtual CHIP_ERROR ClearCallbackOnPendingWrite(SocketWatchToken token) = 0; 261 : 262 : /** 263 : * Stop watching for events on the associated file descriptor. 264 : * 265 : * This MUST be called before the file descriptor is closed. 266 : * It is not necessary to clear callback requests before calling this function. 267 : */ 268 : virtual CHIP_ERROR StopWatchingSocket(SocketWatchToken * tokenInOut) = 0; 269 : 270 : /** 271 : * Return a SocketWatchToken that is guaranteed not to be valid. Clients may use this to initialize variables. 272 : */ 273 : virtual SocketWatchToken InvalidSocketWatchToken() = 0; 274 : }; 275 : 276 : class LayerSocketsLoop : public LayerSockets 277 : { 278 : public: 279 : virtual void Signal() = 0; 280 : virtual void EventLoopBegins() = 0; 281 : virtual void PrepareEvents() = 0; 282 : virtual void WaitForEvents() = 0; 283 : virtual void HandleEvents() = 0; 284 : virtual void EventLoopEnds() = 0; 285 : 286 : #if CHIP_SYSTEM_CONFIG_USE_DISPATCH 287 : virtual void SetDispatchQueue(dispatch_queue_t dispatchQueue) = 0; 288 : virtual dispatch_queue_t GetDispatchQueue() = 0; 289 : #elif CHIP_SYSTEM_CONFIG_USE_LIBEV 290 : virtual void SetLibEvLoop(struct ev_loop * aLibEvLoopP) = 0; 291 : virtual struct ev_loop * GetLibEvLoop() = 0; 292 : #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV 293 : }; 294 : 295 : #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS 296 : 297 : } // namespace System 298 : } // namespace chip