Line data Source code
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 declares the abstraction of one-directional, anonymous 21 : * data stream built on top of two file descriptors. 22 : */ 23 : 24 : #include <system/SystemConfig.h> 25 : 26 : #if CHIP_SYSTEM_CONFIG_USE_SOCKETS && !CHIP_SYSTEM_CONFIG_USE_LIBEV 27 : 28 : #include <system/WakeEvent.h> 29 : 30 : // Include additional CHIP headers 31 : #include <lib/support/CodeUtils.h> 32 : #include <system/SystemError.h> 33 : #include <system/SystemLayer.h> 34 : 35 : // Include system and language headers 36 : #include <errno.h> 37 : #include <fcntl.h> 38 : #include <unistd.h> 39 : 40 : #if !CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE 41 : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_EVENTFD 42 : #include <zephyr/posix/sys/eventfd.h> 43 : #else 44 : #include <sys/eventfd.h> 45 : #endif 46 : #endif // !CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE 47 : 48 : namespace chip { 49 : namespace System { 50 : 51 : #if CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE 52 : 53 : namespace { 54 164 : inline int SetNonBlockingMode(int fd) 55 : { 56 164 : int flags = ::fcntl(fd, F_GETFL, 0); 57 164 : return ::fcntl(fd, F_SETFL, flags | O_NONBLOCK); 58 : } 59 : } // anonymous namespace 60 : 61 82 : CHIP_ERROR WakeEvent::Open(LayerSockets & systemLayer) 62 : { 63 : enum 64 : { 65 : FD_READ = 0, 66 : FD_WRITE = 1 67 : }; 68 : int fds[2]; 69 : 70 82 : if (::pipe(fds) < 0) 71 0 : return CHIP_ERROR_POSIX(errno); 72 : 73 82 : if (SetNonBlockingMode(fds[FD_READ]) < 0) 74 0 : return CHIP_ERROR_POSIX(errno); 75 : 76 82 : if (SetNonBlockingMode(fds[FD_WRITE]) < 0) 77 0 : return CHIP_ERROR_POSIX(errno); 78 : 79 82 : mReadFD = fds[FD_READ]; 80 82 : mWriteFD = fds[FD_WRITE]; 81 : 82 82 : ReturnErrorOnFailure(systemLayer.StartWatchingSocket(mReadFD, &mReadWatch)); 83 82 : ReturnErrorOnFailure(systemLayer.SetCallback(mReadWatch, Confirm, reinterpret_cast<intptr_t>(this))); 84 82 : ReturnErrorOnFailure(systemLayer.RequestCallbackOnPendingRead(mReadWatch)); 85 : 86 82 : return CHIP_NO_ERROR; 87 : } 88 : 89 82 : void WakeEvent::Close(LayerSockets & systemLayer) 90 : { 91 82 : systemLayer.StopWatchingSocket(&mReadWatch); 92 82 : VerifyOrDie(::close(mReadFD) == 0); 93 82 : VerifyOrDie(::close(mWriteFD) == 0); 94 82 : mReadFD = -1; 95 82 : mWriteFD = -1; 96 82 : } 97 : 98 4092505 : void WakeEvent::Confirm() const 99 : { 100 : uint8_t buffer[128]; 101 : ssize_t res; 102 : 103 : do 104 : { 105 4092505 : res = ::read(mReadFD, buffer, sizeof(buffer)); 106 4092505 : if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) 107 : { 108 0 : ChipLogError(chipSystemLayer, "System wake event confirm failed: %" CHIP_ERROR_FORMAT, 109 : CHIP_ERROR_POSIX(errno).Format()); 110 0 : return; 111 : } 112 4092505 : } while (res == sizeof(buffer)); 113 : } 114 : 115 8071747 : CHIP_ERROR WakeEvent::Notify() const 116 : { 117 8071747 : char byte = 1; 118 : 119 8071747 : if (::write(mWriteFD, &byte, 1) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) 120 : { 121 1 : return CHIP_ERROR_POSIX(errno); 122 : } 123 : 124 8071746 : return CHIP_NO_ERROR; 125 : } 126 : 127 : #else // CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE 128 : 129 : namespace { 130 : 131 : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_EVENTFD 132 : 133 : int ReadEvent(int eventFd) 134 : { 135 : eventfd_t value; 136 : 137 : return eventfd_read(eventFd, &value); 138 : } 139 : 140 : int WriteEvent(int eventFd) 141 : { 142 : return eventfd_write(eventFd, 1); 143 : } 144 : 145 : #else 146 : 147 : ssize_t ReadEvent(int eventFd) 148 : { 149 : uint64_t value; 150 : 151 : return ::read(eventFd, &value, sizeof(value)); 152 : } 153 : 154 : ssize_t WriteEvent(int eventFd) 155 : { 156 : uint64_t value = 1; 157 : 158 : return ::write(eventFd, &value, sizeof(value)); 159 : } 160 : 161 : #endif 162 : 163 : } // namespace 164 : 165 : CHIP_ERROR WakeEvent::Open(LayerSockets & systemLayer) 166 : { 167 : mReadFD = ::eventfd(0, 0); 168 : if (mReadFD == -1) 169 : { 170 : return CHIP_ERROR_POSIX(errno); 171 : } 172 : 173 : ReturnErrorOnFailure(systemLayer.StartWatchingSocket(mReadFD, &mReadWatch)); 174 : ReturnErrorOnFailure(systemLayer.SetCallback(mReadWatch, Confirm, reinterpret_cast<intptr_t>(this))); 175 : ReturnErrorOnFailure(systemLayer.RequestCallbackOnPendingRead(mReadWatch)); 176 : 177 : return CHIP_NO_ERROR; 178 : } 179 : 180 : void WakeEvent::Close(LayerSockets & systemLayer) 181 : { 182 : systemLayer.StopWatchingSocket(&mReadWatch); 183 : VerifyOrDie(::close(mReadFD) == 0); 184 : mReadFD = -1; 185 : } 186 : 187 : void WakeEvent::Confirm() const 188 : { 189 : if (ReadEvent(mReadFD) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) 190 : { 191 : ChipLogError(chipSystemLayer, "System wake event confirm failed: %" CHIP_ERROR_FORMAT, CHIP_ERROR_POSIX(errno).Format()); 192 : } 193 : } 194 : 195 : CHIP_ERROR WakeEvent::Notify() const 196 : { 197 : if (WriteEvent(mReadFD) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) 198 : { 199 : return CHIP_ERROR_POSIX(errno); 200 : } 201 : 202 : return CHIP_NO_ERROR; 203 : } 204 : 205 : #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE 206 : 207 : } // namespace System 208 : } // namespace chip 209 : 210 : #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && !CHIP_SYSTEM_CONFIG_USE_LIBEV