1 /*
2  * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "evloop.h"
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <sys/epoll.h>
20 #include "common.h"
21 #include "log.h"
22 
23 #undef LOG_TAG
24 #define LOG_TAG "WifiRpcEventLoop"
25 
26 const int ELOOP_MAX_FD_SIZE = 1024;
27 
CreateEventLoop(int size)28 EventLoop *CreateEventLoop(int size)
29 {
30     int flag = 0; /* flag here is used to indicate whether a failure occurs when create event loop struct, 0:success
31                      1:failure */
32     EventLoop *evLoop = NULL;
33     do {
34         evLoop = (EventLoop *)calloc(1, sizeof(EventLoop));
35         if (evLoop == NULL) {
36             LOGE("Failed to calloc EventLoop struct!");
37             return NULL;
38         }
39         evLoop->setSize = size;
40         evLoop->epfd = -1;
41         if (size <= 0) {
42             free(evLoop);
43             evLoop = NULL;
44             return NULL;
45         }
46         evLoop->fdMasks = (FdMask *)calloc(size, sizeof(FdMask));
47         evLoop->epEvents = (struct epoll_event *)calloc(size, sizeof(struct epoll_event));
48         if (evLoop->fdMasks == NULL || evLoop->epEvents == NULL) {
49             flag = 1; /* fail */
50             LOGE("Failed to calloc events or epoll_event struct!");
51             break;
52         }
53         evLoop->epfd = epoll_create(ELOOP_MAX_FD_SIZE);
54         if (evLoop->epfd == -1) {
55             flag = 1; /* fail */
56             LOGE("Failed to call epoll_create!");
57             break;
58         }
59     } while (0);
60     if (flag == 0) {
61         return evLoop;
62     }
63     if (evLoop->fdMasks != NULL) {
64         free(evLoop->fdMasks);
65         evLoop->fdMasks = NULL;
66     }
67     if (evLoop->epEvents != NULL) {
68         free(evLoop->epEvents);
69         evLoop->epEvents = NULL;
70     }
71     free(evLoop);
72     evLoop = NULL;
73     return NULL;
74 }
75 
DestroyEventLoop(EventLoop * loop)76 void DestroyEventLoop(EventLoop *loop)
77 {
78     if (loop == NULL) {
79         return;
80     }
81 
82     if (loop->epfd != -1) {
83         close(loop->epfd);
84     }
85     if (loop->fdMasks != NULL) {
86         free(loop->fdMasks);
87     }
88     if (loop->epEvents != NULL) {
89         free(loop->epEvents);
90     }
91     free(loop);
92     loop = NULL;
93     return;
94 }
95 
StopEventLoop(EventLoop * loop)96 void StopEventLoop(EventLoop *loop)
97 {
98     if (loop == NULL) {
99         return;
100     }
101 
102     loop->stop = 1;
103     return;
104 }
105 
AddFdEvent(EventLoop * loop,int fd,unsigned int addMask)106 int AddFdEvent(EventLoop *loop, int fd, unsigned int addMask)
107 {
108     if (loop == NULL) {
109         return -1;
110     }
111 
112     if (fd >= loop->setSize) {
113         return -1;
114     }
115     if (loop->fdMasks[fd].mask & addMask) {
116         return 0;
117     }
118     int op = (loop->fdMasks[fd].mask == NONE_EVENT) ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
119     addMask |= loop->fdMasks[fd].mask;
120     struct epoll_event pollEvent = {0};
121     if (addMask & READ_EVENT) {
122         pollEvent.events |= EPOLLIN;
123     }
124     if (addMask & WRIT_EVENT) {
125         pollEvent.events |= EPOLLOUT;
126     }
127     pollEvent.data.fd = fd;
128     if (epoll_ctl(loop->epfd, op, fd, &pollEvent) == -1) {
129         return -1;
130     }
131     loop->fdMasks[fd].fd = fd;
132     loop->fdMasks[fd].mask |= addMask;
133     if (fd > loop->maxFd) {
134         loop->maxFd = fd;
135     }
136     return 0;
137 }
138 
DelFdEvent(EventLoop * loop,int fd,unsigned int delMask)139 int DelFdEvent(EventLoop *loop, int fd, unsigned int delMask)
140 {
141     if (loop == NULL) {
142         return -1;
143     }
144 
145     if (fd >= loop->setSize) {
146         return 0;
147     }
148     if (loop->fdMasks[fd].mask == NONE_EVENT) {
149         return 0;
150     }
151     if ((loop->fdMasks[fd].mask & delMask) == 0) {
152         return 0;
153     }
154     unsigned int mask = loop->fdMasks[fd].mask & (~delMask);
155     struct epoll_event pollEvent = {0};
156     pollEvent.events = 0;
157     if (mask & READ_EVENT) {
158         pollEvent.events |= EPOLLIN;
159     }
160     if (mask & WRIT_EVENT) {
161         pollEvent.events |= EPOLLOUT;
162     }
163     pollEvent.data.fd = fd;
164     int op = (mask == NONE_EVENT) ? EPOLL_CTL_DEL : EPOLL_CTL_MOD;
165     if (epoll_ctl(loop->epfd, op, fd, &pollEvent) == -1) {
166         return -1;
167     }
168     loop->fdMasks[fd].mask &= ~delMask;
169     if (fd == loop->maxFd && loop->fdMasks[fd].mask == NONE_EVENT) {
170         int j = loop->maxFd - 1;
171         for (; j >= 0; --j) {
172             if (loop->fdMasks[j].mask != NONE_EVENT) {
173                 break;
174             }
175         }
176         loop->maxFd = j;
177     }
178 
179     return 0;
180 }
181