Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 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 declares an implementation of System::Layer using select(). 21 : */ 22 : 23 : #pragma once 24 : 25 : #include "system/SystemConfig.h" 26 : 27 : #if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS 28 : #include <sys/select.h> 29 : #endif 30 : 31 : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKETS 32 : #include <zephyr/net/socket.h> 33 : #endif 34 : 35 : #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING 36 : #include <atomic> 37 : #include <pthread.h> 38 : #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING 39 : 40 : #if CHIP_SYSTEM_CONFIG_USE_LIBEV 41 : #include <ev.h> 42 : #if CHIP_SYSTEM_CONFIG_USE_DISPATCH 43 : #error "CHIP_SYSTEM_CONFIG_USE_LIBEV and CHIP_SYSTEM_CONFIG_USE_DISPATCH are mutually exclusive" 44 : #endif 45 : #endif // CHIP_SYSTEM_CONFIG_USE_LIBEV 46 : 47 : #include <lib/support/ObjectLifeCycle.h> 48 : #include <system/SystemLayer.h> 49 : #include <system/SystemTimer.h> 50 : #include <system/WakeEvent.h> 51 : 52 : namespace chip { 53 : namespace System { 54 : 55 : class LayerImplSelect : public LayerSocketsLoop 56 : { 57 : public: 58 : LayerImplSelect() = default; 59 0 : ~LayerImplSelect() override { VerifyOrDie(mLayerState.Destroy()); } 60 : 61 : // Layer overrides. 62 : CHIP_ERROR Init() override; 63 : void Shutdown() override; 64 108 : bool IsInitialized() const override { return mLayerState.IsInitialized(); } 65 : CHIP_ERROR StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; 66 : CHIP_ERROR ExtendTimerTo(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; 67 : bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) override; 68 : void CancelTimer(TimerCompleteCallback onComplete, void * appState) override; 69 : CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState) override; 70 : 71 : // LayerSocket overrides. 72 : CHIP_ERROR StartWatchingSocket(int fd, SocketWatchToken * tokenOut) override; 73 : CHIP_ERROR SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data) override; 74 : CHIP_ERROR RequestCallbackOnPendingRead(SocketWatchToken token) override; 75 : CHIP_ERROR RequestCallbackOnPendingWrite(SocketWatchToken token) override; 76 : CHIP_ERROR ClearCallbackOnPendingRead(SocketWatchToken token) override; 77 : CHIP_ERROR ClearCallbackOnPendingWrite(SocketWatchToken token) override; 78 : CHIP_ERROR StopWatchingSocket(SocketWatchToken * tokenInOut) override; 79 165 : SocketWatchToken InvalidSocketWatchToken() override { return reinterpret_cast<SocketWatchToken>(nullptr); } 80 : 81 : // LayerSocketLoop overrides. 82 : void Signal() override; 83 54 : void EventLoopBegins() override {} 84 : void PrepareEvents() override; 85 : void WaitForEvents() override; 86 : void HandleEvents() override; 87 54 : void EventLoopEnds() override {} 88 : 89 : #if CHIP_SYSTEM_CONFIG_USE_DISPATCH 90 : void SetDispatchQueue(dispatch_queue_t dispatchQueue) override { mDispatchQueue = dispatchQueue; }; 91 : dispatch_queue_t GetDispatchQueue() override { return mDispatchQueue; }; 92 : void HandleTimerComplete(TimerList::Node * timer); 93 : #elif CHIP_SYSTEM_CONFIG_USE_LIBEV 94 : virtual void SetLibEvLoop(struct ev_loop * aLibEvLoopP) override { mLibEvLoopP = aLibEvLoopP; }; 95 : virtual struct ev_loop * GetLibEvLoop() override { return mLibEvLoopP; }; 96 : static void HandleLibEvTimer(EV_P_ struct ev_timer * t, int revents); 97 : static void HandleLibEvIoWatcher(EV_P_ struct ev_io * i, int revents); 98 : #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV 99 : 100 : // Expose the result of WaitForEvents() for non-blocking socket implementations. 101 4092525 : bool IsSelectResultValid() const { return mSelectResult >= 0; } 102 : 103 : protected: 104 : static SocketEvents SocketEventsFromFDs(int socket, const fd_set & readfds, const fd_set & writefds, const fd_set & exceptfds); 105 : 106 : static constexpr int kSocketWatchMax = (INET_CONFIG_ENABLE_TCP_ENDPOINT ? INET_CONFIG_NUM_TCP_ENDPOINTS : 0) + 107 : (INET_CONFIG_ENABLE_UDP_ENDPOINT ? INET_CONFIG_NUM_UDP_ENDPOINTS : 0); 108 : 109 : struct SocketWatch 110 : { 111 : void Clear(); 112 : int mFD; 113 : SocketEvents mPendingIO; 114 : SocketWatchCallback mCallback; 115 : #if CHIP_SYSTEM_CONFIG_USE_DISPATCH 116 : dispatch_source_t mRdSource; 117 : dispatch_source_t mWrSource; 118 : void DisableAndClear(); 119 : #endif 120 : #if CHIP_SYSTEM_CONFIG_USE_LIBEV 121 : struct ev_io mIoWatcher; 122 : LayerImplSelect * mLayerImplSelectP; 123 : void DisableAndClear(); 124 : #endif 125 : 126 : intptr_t mCallbackData; 127 : }; 128 : SocketWatch mSocketWatchPool[kSocketWatchMax]; 129 : 130 : TimerPool<TimerList::Node> mTimerPool; 131 : TimerList mTimerList; 132 : // List of expired timers being processed right now. Stored in a member so 133 : // we can cancel them. 134 : TimerList mExpiredTimers; 135 : timeval mNextTimeout; 136 : 137 : // Members for select loop 138 : struct SelectSets 139 : { 140 : fd_set mReadSet; 141 : fd_set mWriteSet; 142 : fd_set mErrorSet; 143 : }; 144 : SelectSets mSelected; 145 : int mMaxFd; 146 : 147 : // Return value from select(), carried between WaitForEvents() and HandleEvents(). 148 : int mSelectResult; 149 : 150 : ObjectLifeCycle mLayerState; 151 : #if !CHIP_SYSTEM_CONFIG_USE_LIBEV 152 : WakeEvent mWakeEvent; 153 : #endif 154 : 155 : #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING 156 : std::atomic<pthread_t> mHandleSelectThread; 157 : #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING 158 : 159 : #if CHIP_SYSTEM_CONFIG_USE_DISPATCH 160 : dispatch_queue_t mDispatchQueue = nullptr; 161 : #elif CHIP_SYSTEM_CONFIG_USE_LIBEV 162 : struct ev_loop * mLibEvLoopP; 163 : #endif 164 : }; 165 : 166 : using LayerImpl = LayerImplSelect; 167 : 168 : } // namespace System 169 : } // namespace chip