1 /*
2 * Copyright (C) 2021 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 "securec.h"
17 #include "nstackx_epoll.h"
18 #include "nstackx_log.h"
19 #include "nstackx_error.h"
20 #include "nstackx_list.h"
21 #include "nstackx_socket.h"
22 #include "nstackx_timer.h"
23
24 #define TAG "nStackXEpoll"
25
26 #ifndef LWIP_LITEOS_A_COMPAT
27 #define IS_INVALID_SOCKET_DESC(fd) \
28 (((fd) < LWIP_SOCKET_OFFSET) || ((fd) >= (LWIP_CONFIG_NUM_SOCKETS + LWIP_SOCKET_OFFSET)))
29 #define EVENT_PTR_IDX(fd) ((fd) - (LWIP_SOCKET_OFFSET))
30 #else
31 #define IS_INVALID_SOCKET_DESC(fd) ((fd) < 0)
32 #endif /* LWIP_LITEOS_A_COMPAT */
33
34 typedef struct {
35 fd_set *readfds;
36 fd_set *writefds;
37 fd_set *exceptfds;
38 } EpollSetPtr;
39
40 typedef struct {
41 struct EpollDescStr epollfd;
42 int32_t maxfd;
43 fd_set readfds;
44 fd_set writefds;
45 fd_set exceptfds;
46 pthread_mutex_t mutex;
47 } EpollSet;
48
49 #ifdef LWIP_LITEOS_A_COMPAT
50 struct EpollTaskList {
51 List list;
52 EpollTask *taskPtr;
53 };
54
55 struct EpollEventPtr {
56 List list;
57 List taskList;
58 EpollSet *epollSetPtr;
59 };
60 #else
61 struct EpollEventPtr {
62 EpollSet *epollSetPtr;
63 EpollTask *taskPtr;
64 };
65 #endif
66
67 typedef void (*EpollTraverseFunc)(EpollSet *epollSetPtr, void *param, int32_t fd);
68 typedef void (*EpollEventCtrlFunc)(EpollSet *epollSetPtr, uint32_t events, EpollTask *task);
69
70 static uint8_t g_epollInited = NSTACKX_FALSE;
71 static pthread_mutex_t g_epollEventPtrMutex;
72
73 #ifdef LWIP_LITEOS_A_COMPAT
74 static List g_epollEventPtrList;
75 #else
76 static struct EpollEventPtr *g_epollEventPtrArray = NULL;
77 #endif
78
79 static void EpollFdEventAdd(EpollSet *epollSetPtr, uint32_t events, EpollTask *task);
80 static void EpollFdEventDel(EpollSet *epollSetPtr, uint32_t events, EpollTask *task);
81 static void EpollFdEventMod(EpollSet *epollSetPtr, uint32_t events, EpollTask *task);
82
CtlEpollDesc(EpollTask * task,int op,uint32_t events)83 static int32_t CtlEpollDesc(EpollTask *task, int op, uint32_t events)
84 {
85 struct EpollEvent event;
86 #ifdef NSTACKX_DEBUG
87 static uint32_t evtCnt = 0;
88 #endif
89
90 if ((task == NULL) || ((op != EPOLL_CTL_RUN) && IS_INVALID_SOCKET_DESC(task->taskfd)) ||
91 (!IsEpollDescValid(task->epollfd))) {
92 LOGE(TAG, "invalid params");
93 return NSTACKX_EINVAL;
94 }
95
96 event.op = op;
97 event.events = events;
98 event.ptr = (void *)task;
99 #ifdef NSTACKX_DEBUG
100 event.evtSeq = evtCnt++;
101 LOGD(TAG, "%d op %d event seq: %u", task->epollfd->recvFd, op, event.evtSeq);
102 #endif
103 if (sendto(task->epollfd->sendFd, (const void *)&event, sizeof(event), 0, NULL, 0) < 0) {
104 LOGE(TAG, "ctrl epollfd failed: %d", errno);
105 return NSTACKX_EFAILED;
106 }
107
108 return NSTACKX_EOK;
109 }
110
CtlEpollDescSync(EpollTask * task,EpollEventCtrlFunc func,uint32_t events)111 static int32_t CtlEpollDescSync(EpollTask *task, EpollEventCtrlFunc func, uint32_t events)
112 {
113 EpollSet *epollSetPtr = NULL;
114 if ((task == NULL) || IS_INVALID_SOCKET_DESC(task->taskfd) || (!IsEpollDescValid(task->epollfd))) {
115 LOGE(TAG, "invalid params");
116 return NSTACKX_EINVAL;
117 }
118
119 epollSetPtr = container_of(task->epollfd, EpollSet, epollfd);
120 if (pthread_mutex_lock(&(epollSetPtr->mutex)) != 0) {
121 LOGE(TAG, "pthread mutex lock error");
122 return NSTACKX_EFAILED;
123 }
124 func(epollSetPtr, events, task);
125 if (pthread_mutex_unlock(&(epollSetPtr->mutex)) != 0) {
126 LOGE(TAG, "pthread mutex unlock error");
127 }
128
129 return NSTACKX_EOK;
130 }
131
RunEpollTask(void * task,uint32_t events)132 int32_t RunEpollTask(void *task, uint32_t events)
133 {
134 return CtlEpollDesc((EpollTask *)task, EPOLL_CTL_RUN, events);
135 }
136
RefreshEpollTask(EpollTask * task,uint32_t events)137 int32_t RefreshEpollTask(EpollTask *task, uint32_t events)
138 {
139 return CtlEpollDescSync(task, EpollFdEventMod, events);
140 }
141
RegisterEpollTask(EpollTask * task,uint32_t events)142 int32_t RegisterEpollTask(EpollTask *task, uint32_t events)
143 {
144 return CtlEpollDescSync(task, EpollFdEventAdd, events);
145 }
146
DeRegisterEpollTask(EpollTask * task)147 int32_t DeRegisterEpollTask(EpollTask *task)
148 {
149 return CtlEpollDescSync(task, EpollFdEventDel, 0);
150 }
151
152 #ifdef LWIP_LITEOS_A_COMPAT
EpollSetFindByFd(int32_t fd)153 static EpollSet *EpollSetFindByFd(int32_t fd)
154 {
155 List *curr = NULL;
156 struct EpollEventPtr *ptr = NULL;
157 LIST_FOR_EACH(curr, &g_epollEventPtrList) {
158 ptr = container_of(curr, struct EpollEventPtr, list);
159 if (FD_ISSET(fd, &(ptr->epollSetPtr->exceptfds))) {
160 return ptr->epollSetPtr;
161 }
162 }
163 return NULL;
164 }
165
EpollEventListFind(const EpollSet * epollSetPtr)166 static struct EpollEventPtr *EpollEventListFind(const EpollSet *epollSetPtr)
167 {
168 List *curr = NULL;
169 struct EpollEventPtr *ptr = NULL;
170 LIST_FOR_EACH(curr, &g_epollEventPtrList) {
171 ptr = container_of(curr, struct EpollEventPtr, list);
172 if (ptr->epollSetPtr == epollSetPtr) {
173 return ptr;
174 }
175 }
176 return NULL;
177 }
178
EpollTaskListFind(const struct EpollEventPtr * ptr,const EpollTask * task)179 static struct EpollTaskList *EpollTaskListFind(const struct EpollEventPtr *ptr, const EpollTask *task)
180 {
181 List *curr = NULL;
182 struct EpollTaskList *taskListPtr = NULL;
183 LIST_FOR_EACH(curr, &(ptr->taskList)) {
184 taskListPtr = container_of(curr, struct EpollTaskList, list);
185 if (taskListPtr->taskPtr == task) {
186 return taskListPtr;
187 }
188 }
189 return NULL;
190 }
191
EpollTaskListNew(EpollTask * task)192 static struct EpollTaskList *EpollTaskListNew(EpollTask *task)
193 {
194 struct EpollTaskList *taskListPtr = (struct EpollTaskList *)malloc(sizeof(struct EpollTaskList));
195 if (taskListPtr == NULL) {
196 LOGE(TAG, "alloc EpollTaskList failed");
197 return NULL;
198 }
199 (void)memset_s(taskListPtr, sizeof(*taskListPtr), 0, sizeof(*taskListPtr));
200 taskListPtr->taskPtr = task;
201 ListInitHead(&(taskListPtr->list));
202 return taskListPtr;
203 }
204
EpollEventTaskListAdd(const EpollSet * epollSetPtr,EpollTask * task)205 static int32_t EpollEventTaskListAdd(const EpollSet *epollSetPtr, EpollTask *task)
206 {
207 struct EpollEventPtr *ptr = EpollEventListFind(epollSetPtr);
208 struct EpollTaskList *taskListPtr = NULL;
209 if (ptr == NULL) {
210 LOGE(TAG, "EpollSet not in list");
211 return NSTACKX_NOEXIST;
212 }
213 taskListPtr = EpollTaskListNew(task);
214 if (taskListPtr == NULL) {
215 return NSTACKX_ENOMEM;
216 }
217 ListInsertTail(&(ptr->taskList), &(taskListPtr->list));
218 return NSTACKX_EOK;
219 }
220
EpollEventTaskListDel(const EpollSet * epollSetPtr,const EpollTask * task)221 static void EpollEventTaskListDel(const EpollSet *epollSetPtr, const EpollTask *task)
222 {
223 struct EpollEventPtr *ptr = EpollEventListFind(epollSetPtr);
224 struct EpollTaskList *taskListPtr = NULL;
225 if (ptr == NULL) {
226 LOGE(TAG, "EpollSet not in list");
227 return;
228 }
229 taskListPtr = EpollTaskListFind(ptr, task);
230 if (taskListPtr == NULL) {
231 return;
232 }
233 ListRemoveNode(&(taskListPtr->list));
234 free(taskListPtr);
235 return;
236 }
237
EpollTaskFindByFd(const struct EpollEventPtr * ptr,int32_t fd)238 static EpollTask *EpollTaskFindByFd(const struct EpollEventPtr *ptr, int32_t fd)
239 {
240 List *curr = NULL;
241 struct EpollTaskList *taskListPtr = NULL;
242 LIST_FOR_EACH(curr, &(ptr->taskList)) {
243 taskListPtr = container_of(curr, struct EpollTaskList, list);
244 if (taskListPtr->taskPtr->taskfd == fd) {
245 return taskListPtr->taskPtr;
246 }
247 }
248 return NULL;
249 }
250
EpollSetFindTaskByFd(const EpollSet * epollSetPtr,int32_t fd)251 static EpollTask *EpollSetFindTaskByFd(const EpollSet *epollSetPtr, int32_t fd)
252 {
253 struct EpollEventPtr *ptr = EpollEventListFind(epollSetPtr);
254 if (ptr == NULL) {
255 LOGE(TAG, "EpollSet not in list");
256 return NULL;
257 }
258 return EpollTaskFindByFd(ptr, fd);
259 }
260 #endif /* LWIP_LITEOS_A_COMPAT */
261
ConnectPeerFd(int32_t localFd,int32_t peerFd)262 static int32_t ConnectPeerFd(int32_t localFd, int32_t peerFd)
263 {
264 struct sockaddr_in addr = {0};
265 socklen_t addr_len = sizeof(addr);
266
267 if (getsockname(peerFd, (struct sockaddr *)&addr, &addr_len) != 0) {
268 LOGE(TAG, "getsockname failed: %d", errno);
269 return NSTACKX_EFAILED;
270 }
271 if (connect(localFd, (struct sockaddr *)&addr, addr_len) != 0) {
272 LOGE(TAG, "connect failed: %d", errno);
273 return NSTACKX_EFAILED;
274 }
275
276 return NSTACKX_EOK;
277 }
278
GetLoopbackFd(int32_t peerFd)279 static int32_t GetLoopbackFd(int32_t peerFd)
280 {
281 int32_t fd;
282 struct sockaddr_in addr = {0};
283 struct sockaddr *sockaddr = NULL;
284 socklen_t addr_len;
285
286 addr.sin_family = AF_INET;
287 addr.sin_port = 0;
288 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
289 sockaddr = (struct sockaddr *)&addr;
290 addr_len = sizeof(addr);
291
292 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
293 if (fd < 0) {
294 LOGE(TAG, "socket failed: %d", errno);
295 return -1;
296 }
297
298 if (SetSocketNonBlock(fd) != NSTACKX_EOK) {
299 LOGE(TAG, "set socket nonblock failed");
300 close(fd);
301 return -1;
302 }
303
304 if (bind(fd, sockaddr, addr_len) != 0) {
305 LOGE(TAG, "bind failed: %d", errno);
306 close(fd);
307 return -1;
308 }
309
310 if (peerFd < 0) {
311 /* if peerFd is invalid, there is no need to connect to it, just return */
312 return fd;
313 }
314
315 if ((ConnectPeerFd(fd, peerFd) == NSTACKX_EFAILED) || (ConnectPeerFd(peerFd, fd) == NSTACKX_EFAILED)) {
316 close(fd);
317 return -1;
318 }
319
320 return fd;
321 }
322
CreateEpollFdPair(struct EpollDescStr * epollfd)323 int32_t CreateEpollFdPair(struct EpollDescStr *epollfd)
324 {
325 if (epollfd == NULL) {
326 LOGE(TAG, "invalid param");
327 return NSTACKX_EINVAL;
328 }
329
330 epollfd->recvFd = GetLoopbackFd(-1);
331 if (epollfd->recvFd < 0) {
332 epollfd->recvFd = -1;
333 epollfd->sendFd = -1;
334 return NSTACKX_EFAILED;
335 }
336
337 epollfd->sendFd = GetLoopbackFd(epollfd->recvFd);
338 if (epollfd->sendFd < 0) {
339 close(epollfd->recvFd);
340 epollfd->recvFd = -1;
341 epollfd->sendFd = -1;
342 return NSTACKX_EFAILED;
343 }
344
345 return NSTACKX_EOK;
346 }
347
EpollEventPtrInit(void)348 void EpollEventPtrInit(void)
349 {
350 if (g_epollInited == NSTACKX_TRUE) {
351 return;
352 }
353 /* this function is called when init lwip thread */
354 if (pthread_mutex_init(&g_epollEventPtrMutex, NULL) != 0) {
355 LOGE(TAG, "pthread_mutex_init error");
356 return;
357 }
358 #ifdef LWIP_LITEOS_A_COMPAT
359 ListInitHead(&g_epollEventPtrList);
360 #else
361 /* as ported to LwIP, once the memory is allocated, it will not be freed ever */
362 g_epollEventPtrArray = (struct EpollEventPtr *)malloc(LWIP_CONFIG_NUM_SOCKETS * sizeof(struct EpollEventPtr));
363 if (g_epollEventPtrArray == NULL) {
364 LOGE(TAG, "malloc epoll ptr array failed");
365 return;
366 }
367 (void)memset_s(g_epollEventPtrArray, LWIP_CONFIG_NUM_SOCKETS * sizeof(struct EpollEventPtr), 0x0,
368 LWIP_CONFIG_NUM_SOCKETS * sizeof(struct EpollEventPtr));
369 #endif
370 g_epollInited = NSTACKX_TRUE;
371 LOGD(TAG, "epoll event init success");
372 return;
373 }
374
EpollEventRecordAdd(EpollSet * epollSetPtr)375 static int32_t EpollEventRecordAdd(EpollSet *epollSetPtr)
376 {
377 if (pthread_mutex_lock(&g_epollEventPtrMutex) != 0) {
378 LOGE(TAG, "pthread mutex lock error");
379 return NSTACKX_EFAILED;
380 }
381 #ifdef LWIP_LITEOS_A_COMPAT
382 struct EpollEventPtr *ptr = (struct EpollEventPtr *)malloc(sizeof(struct EpollEventPtr));
383 if (ptr == NULL) {
384 if (pthread_mutex_unlock(&g_epollEventPtrMutex) != 0) {
385 LOGE(TAG, "pthread mutex unlock error");
386 }
387 LOGE(TAG, "EpollEventPtr alloc failed");
388 return NSTACKX_ENOMEM;
389 }
390 (void)memset_s(ptr, sizeof(struct EpollEventPtr), 0, sizeof(struct EpollEventPtr));
391 ListInitHead(&(ptr->list));
392 ListInitHead(&(ptr->taskList));
393 ptr->epollSetPtr = epollSetPtr;
394 ListInsertTail(&g_epollEventPtrList, &(ptr->list));
395 #else
396 g_epollEventPtrArray[EVENT_PTR_IDX(epollSetPtr->epollfd.recvFd)].epollSetPtr = epollSetPtr;
397 g_epollEventPtrArray[EVENT_PTR_IDX(epollSetPtr->epollfd.sendFd)].epollSetPtr = epollSetPtr;
398 #endif
399 if (pthread_mutex_unlock(&g_epollEventPtrMutex) != 0) {
400 /* just give log, no error returned */
401 LOGE(TAG, "pthread mutex unlock error");
402 }
403 return NSTACKX_EOK;
404 }
405
CreateEpollDesc(void)406 EpollDesc CreateEpollDesc(void)
407 {
408 EpollSet *epollSetPtr = NULL;
409
410 if (g_epollInited != NSTACKX_TRUE) {
411 LOGE(TAG, "Epoll Event Ptr Not Init");
412 return NULL;
413 }
414
415 epollSetPtr = (EpollSet *)malloc(sizeof(EpollSet));
416 if (epollSetPtr == NULL) {
417 LOGE(TAG, "malloc EpollSet failed");
418 return NULL;
419 }
420 (void)memset_s(epollSetPtr, sizeof(EpollSet), 0, sizeof(EpollSet));
421
422 if (pthread_mutex_init(&(epollSetPtr->mutex), NULL) != 0) {
423 LOGE(TAG, "pthread_mutex_init error");
424 goto FAIL_FREE;
425 }
426
427 if (CreateEpollFdPair(&(epollSetPtr->epollfd)) != NSTACKX_EOK) {
428 LOGE(TAG, "Create Epoll failed");
429 goto FAIL_MUTEX;
430 }
431
432 FD_SET(epollSetPtr->epollfd.recvFd, &epollSetPtr->readfds);
433 FD_SET(epollSetPtr->epollfd.recvFd, &epollSetPtr->exceptfds);
434 epollSetPtr->maxfd = epollSetPtr->epollfd.recvFd;
435
436 if (EpollEventRecordAdd(epollSetPtr) != NSTACKX_EOK) {
437 goto FAIL_CLOSE;
438 }
439
440 return &(epollSetPtr->epollfd);
441 FAIL_CLOSE:
442 close(epollSetPtr->epollfd.recvFd);
443 close(epollSetPtr->epollfd.sendFd);
444 FAIL_MUTEX:
445 if (pthread_mutex_destroy(&(epollSetPtr->mutex)) != 0) {
446 LOGE(TAG, "pthread mutex destroy error: %d", errno);
447 }
448 FAIL_FREE:
449 free(epollSetPtr);
450 return NULL;
451 }
452
RearZeroBitNum(unsigned long x)453 static int32_t RearZeroBitNum(unsigned long x)
454 {
455 int32_t n = 1;
456 int bitMov = TYPE_BITS_NUM(x) >> 1;
457 int bitNum = bitMov;
458
459 /* through binarySearch */
460 while (bitNum > 1) {
461 if ((x << bitMov) == 0) {
462 n = n + bitNum;
463 x = x >> bitNum;
464 }
465 bitNum = bitNum >> 1;
466 bitMov += bitNum;
467 }
468
469 n = n - (x & 1);
470 return n;
471 }
472
PreZeroBitNum(unsigned long x)473 static int32_t PreZeroBitNum(unsigned long x)
474 {
475 int n = 1;
476 int bitMov = TYPE_BITS_NUM(x) >> 1;
477 int bitNum = bitMov;
478
479 /* through binarySearch */
480 while (bitNum > 1) {
481 if ((x >> bitMov) == 0) {
482 n = n + bitNum;
483 x = x << bitNum;
484 }
485 bitNum = bitNum >> 1;
486 bitMov += bitNum;
487 }
488
489 n = n - (x >> (TYPE_BITS_NUM(x) - 1));
490 return n;
491 }
492
EpollTaskEventHandle(uint32_t events,EpollTask * task)493 static void EpollTaskEventHandle(uint32_t events, EpollTask *task)
494 {
495 if ((events & EPOLLERR) == EPOLLERR) {
496 if (task->errorHandle != NULL) {
497 task->errorHandle(task);
498 }
499 return;
500 }
501
502 if (((events & EPOLLIN) == EPOLLIN) && (task->readHandle != NULL)) {
503 task->readHandle(task);
504 }
505
506 /* Caution: It is possible for xxxHandle to free the Timer struct part of which the `task` is pointing to.
507 * See ClientSettingTimeoutHandle() and ServerSettingTimeoutHandle() functions for an example. Coders must
508 * logically assert that the `task` pointer will never be dereferenced if its content is previously freed.
509 */
510 if (((events & EPOLLOUT) == EPOLLOUT) && (task->writeHandle != NULL)) {
511 task->writeHandle(task);
512 }
513 }
514
EpollFdEventTaskAdd(EpollSet * epollSetPtr,EpollTask * task)515 static int32_t EpollFdEventTaskAdd(EpollSet *epollSetPtr, EpollTask *task)
516 {
517 int32_t ret = NSTACKX_EOK;
518 if (pthread_mutex_lock(&g_epollEventPtrMutex) != 0) {
519 LOGE(TAG, "pthread mutex lock error");
520 return NSTACKX_EFAILED;
521 }
522 #ifdef LWIP_LITEOS_A_COMPAT
523 if (EpollEventTaskListAdd(epollSetPtr, task) != NSTACKX_EOK) {
524 ret = NSTACKX_EFAILED;
525 }
526 #else
527 g_epollEventPtrArray[EVENT_PTR_IDX(task->taskfd)].epollSetPtr = epollSetPtr;
528 g_epollEventPtrArray[EVENT_PTR_IDX(task->taskfd)].taskPtr = task;
529 #endif
530 if (pthread_mutex_unlock(&g_epollEventPtrMutex) != 0) {
531 LOGE(TAG, "pthread mutex unlock error");
532 }
533 return ret;
534 }
535
EpollFdEventAdd(EpollSet * epollSetPtr,uint32_t events,EpollTask * task)536 static void EpollFdEventAdd(EpollSet *epollSetPtr, uint32_t events, EpollTask *task)
537 {
538 #ifndef LWIP_LITEOS_A_COMPAT
539 EpollSet *setPtr = g_epollEventPtrArray[EVENT_PTR_IDX(task->taskfd)].epollSetPtr;
540 if ((setPtr != NULL) && (setPtr != epollSetPtr)) {
541 LOGE(TAG, "ADD: fd %d ptr has been used", task->taskfd);
542 return;
543 }
544 #endif
545 if (FD_ISSET(task->taskfd, &epollSetPtr->exceptfds)) {
546 LOGD(TAG, "ADD: fd %d has in epoll ctl", task->taskfd);
547 return;
548 }
549 if ((events & (EPOLLIN | EPOLLOUT)) == 0) {
550 LOGI(TAG, "invalid events");
551 return;
552 }
553 if ((events & EPOLLIN) == EPOLLIN) {
554 FD_SET(task->taskfd, &epollSetPtr->readfds);
555 }
556 if ((events & EPOLLOUT) == EPOLLOUT) {
557 FD_SET(task->taskfd, &epollSetPtr->writefds);
558 }
559 FD_SET(task->taskfd, &epollSetPtr->exceptfds);
560
561 if (EpollFdEventTaskAdd(epollSetPtr, task) != NSTACKX_EOK) {
562 FD_CLR(task->taskfd, &epollSetPtr->readfds);
563 FD_CLR(task->taskfd, &epollSetPtr->writefds);
564 FD_CLR(task->taskfd, &epollSetPtr->exceptfds);
565 return;
566 }
567 if (task->taskfd > epollSetPtr->maxfd) {
568 epollSetPtr->maxfd = task->taskfd;
569 }
570 }
571
EpollSetMaxFdUpdate(EpollSet * epollSetPtr)572 static void EpollSetMaxFdUpdate(EpollSet *epollSetPtr)
573 {
574 int32_t i, fd;
575
576 #ifdef __LITEOS__
577 #ifdef FDSETSAFESET
578 for (i = (epollSetPtr->maxfd - LWIP_SOCKET_OFFSET) / BYTE_BITS_NUM; i >= 0; i--) {
579 uint8_t bits = epollSetPtr->exceptfds.fd_bits[i];
580 #else
581 for (i = epollSetPtr->maxfd / NFDBITS; i >= LWIP_SOCKET_OFFSET / NFDBITS; i--) {
582 unsigned long bits = epollSetPtr->exceptfds.fds_bits[i];
583 #endif
584 #else
585 for (i = epollSetPtr->maxfd / __NFDBITS; i >= LWIP_SOCKET_OFFSET / __NFDBITS; i--) {
586 unsigned long bits = (unsigned long)(__FDS_BITS(&(epollSetPtr->exceptfds))[i]);
587 #endif
588 if (bits == 0) {
589 continue;
590 }
591 int32_t bitIdx = PreZeroBitNum(bits);
592 #ifdef __LITEOS__
593 #ifdef FDSETSAFESET
594 fd = i * BYTE_BITS_NUM + (TYPE_BITS_NUM(unsigned long) - 1 - bitIdx) + LWIP_SOCKET_OFFSET;
595 #else
596 fd = i * NFDBITS + (TYPE_BITS_NUM(unsigned long) - 1 - bitIdx);
597 #endif
598 #else
599 fd = i * __NFDBITS + (TYPE_BITS_NUM(unsigned long) - 1 - bitIdx);
600 #endif
601 epollSetPtr->maxfd = fd;
602 break;
603 }
604
605 return;
606 }
607
608 static void EpollFdEventTaskDel(const EpollSet *epollSetPtr, const EpollTask *task)
609 {
610 if (pthread_mutex_lock(&g_epollEventPtrMutex) != 0) {
611 LOGE(TAG, "pthread mutex lock error");
612 return;
613 }
614 #ifdef LWIP_LITEOS_A_COMPAT
615 EpollEventTaskListDel(epollSetPtr, task);
616 #else
617 g_epollEventPtrArray[EVENT_PTR_IDX(task->taskfd)].epollSetPtr = NULL;
618 g_epollEventPtrArray[EVENT_PTR_IDX(task->taskfd)].taskPtr = NULL;
619 #endif
620 if (pthread_mutex_unlock(&g_epollEventPtrMutex) != 0) {
621 LOGE(TAG, "pthread mutex unlock error");
622 }
623 }
624
625 static void EpollFdEventDel(EpollSet *epollSetPtr, uint32_t events, EpollTask *task)
626 {
627 #ifndef LWIP_LITEOS_A_COMPAT
628 EpollSet *setPtr = g_epollEventPtrArray[EVENT_PTR_IDX(task->taskfd)].epollSetPtr;
629 if ((setPtr != NULL) && (setPtr != epollSetPtr)) {
630 LOGE(TAG, "DEL: fd %d ptr has been used", task->taskfd);
631 return;
632 }
633 #endif
634 (void)events;
635 if (!FD_ISSET(task->taskfd, &epollSetPtr->exceptfds)) {
636 LOGD(TAG, "DEL: fd %d not in epoll ctl", task->taskfd);
637 return;
638 }
639 FD_CLR(task->taskfd, &epollSetPtr->readfds);
640 FD_CLR(task->taskfd, &epollSetPtr->writefds);
641 FD_CLR(task->taskfd, &epollSetPtr->exceptfds);
642
643 EpollFdEventTaskDel(epollSetPtr, task);
644
645 if (task->taskfd == epollSetPtr->maxfd) {
646 EpollSetMaxFdUpdate(epollSetPtr);
647 }
648
649 return;
650 }
651
652 static void EpollFdEventMod(EpollSet *epollSetPtr, uint32_t events, EpollTask *task)
653 {
654 #ifndef LWIP_LITEOS_A_COMPAT
655 EpollSet *setPtr = g_epollEventPtrArray[EVENT_PTR_IDX(task->taskfd)].epollSetPtr;
656 if ((setPtr != NULL) && (setPtr != epollSetPtr)) {
657 LOGE(TAG, "MOD: fd %d ptr has been used", task->taskfd);
658 return;
659 }
660 #endif
661 if (!FD_ISSET(task->taskfd, &epollSetPtr->exceptfds)) {
662 LOGD(TAG, "MOD: fd %d not in epoll ctl", task->taskfd);
663 return;
664 }
665 if ((events & (EPOLLIN | EPOLLOUT)) == 0) {
666 LOGI(TAG, "invalid events");
667 return;
668 }
669 FD_CLR(task->taskfd, &epollSetPtr->readfds);
670 FD_CLR(task->taskfd, &epollSetPtr->writefds);
671 if ((events & EPOLLIN) == EPOLLIN) {
672 FD_SET(task->taskfd, &epollSetPtr->readfds);
673 }
674 if ((events & EPOLLOUT) == EPOLLOUT) {
675 FD_SET(task->taskfd, &epollSetPtr->writefds);
676 }
677
678 return;
679 }
680
681 static void EpollFdEventRun(EpollSet *epollSetPtr, uint32_t events, EpollTask *task)
682 {
683 (void)epollSetPtr;
684 EpollTaskEventHandle(events, task);
685 }
686
687 static void EpollFdEventOpHandle(EpollSet *epollSetPtr, int op, uint32_t events, EpollTask *task)
688 {
689 switch (op) {
690 case EPOLL_CTL_ADD:
691 case EPOLL_CTL_DEL:
692 case EPOLL_CTL_MOD:
693 break;
694 case EPOLL_CTL_RUN:
695 EpollFdEventRun(epollSetPtr, events, task);
696 break;
697 default:
698 LOGI(TAG, "unsupported op %u", op);
699 break;
700 }
701 }
702
703 static void EpollFdEventHandle(EpollSet *epollSetPtr, fd_set *readfds)
704 {
705 int32_t ret;
706 EpollTask *task = NULL;
707 struct EpollEvent event;
708 if (!FD_ISSET(epollSetPtr->epollfd.recvFd, readfds)) {
709 return;
710 }
711
712 while (NSTACKX_TRUE) {
713 ret = recvfrom(epollSetPtr->epollfd.recvFd, (void *)&event, sizeof(event), 0, NULL, NULL);
714 if (ret < (int32_t)(sizeof(event))) {
715 break;
716 }
717 #ifdef NSTACKX_DEBUG
718 LOGD(TAG, "Handle task %d event seq: %u", epollSetPtr->epollfd.recvFd, event.evtSeq);
719 #endif
720 task = (EpollTask *)event.ptr;
721 if (task == NULL) {
722 continue;
723 }
724 EpollFdEventOpHandle(epollSetPtr, event.op, event.events, task);
725 }
726 }
727
728 static void EpollEventHandle(EpollSet *epollSetPtr, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, int32_t fd)
729 {
730 uint32_t events = 0;
731 EpollTask *task = NULL;
732
733 #ifdef LWIP_LITEOS_A_COMPAT
734 task = EpollSetFindTaskByFd(epollSetPtr, fd);
735 #else
736 EpollSet *setPtr = g_epollEventPtrArray[EVENT_PTR_IDX(fd)].epollSetPtr;
737 if (setPtr != epollSetPtr) {
738 return;
739 }
740 task = g_epollEventPtrArray[EVENT_PTR_IDX(fd)].taskPtr;
741 #endif
742 if (task == NULL) {
743 return;
744 }
745
746 if (FD_ISSET(fd, readfds)) {
747 events |= EPOLLIN;
748 }
749 if (FD_ISSET(fd, writefds)) {
750 events |= EPOLLOUT;
751 }
752 if (FD_ISSET(fd, exceptfds)) {
753 events |= EPOLLERR;
754 }
755 if (events == 0) {
756 return;
757 }
758
759 EpollTaskEventHandle(events, task);
760 }
761
762 static void EpollSetFdHandle(EpollSet *epollSetPtr, void *param, int32_t fd)
763 {
764 EpollSetPtr *setPtr = (EpollSetPtr *)param;
765 fd_set *readfds = setPtr->readfds;
766 fd_set *writefds = setPtr->writefds;
767 fd_set *exceptfds = setPtr->exceptfds;
768 if (fd == epollSetPtr->epollfd.recvFd) {
769 EpollFdEventHandle(epollSetPtr, readfds);
770 #ifdef LWIP_LITEOS_A_COMPAT
771 } else {
772 #else
773 } else if (g_epollEventPtrArray[EVENT_PTR_IDX(fd)].epollSetPtr == epollSetPtr) {
774 #endif
775 EpollEventHandle(epollSetPtr, readfds, writefds, exceptfds, fd);
776 }
777 }
778
779 static void EpollSetTraverse(EpollSet *epollSetPtr, EpollTraverseFunc func, void *param)
780 {
781 #ifdef __LITEOS__
782 #ifdef FDSETSAFESET
783 for (int32_t i = 0; i <= (epollSetPtr->maxfd - LWIP_SOCKET_OFFSET) / BYTE_BITS_NUM; i++) {
784 uint8_t bits = epollSetPtr->exceptfds.fd_bits[i];
785 #else
786 for (int32_t i = LWIP_SOCKET_OFFSET / NFDBITS; i <= epollSetPtr->maxfd / NFDBITS; i++) {
787 unsigned long bits = epollSetPtr->exceptfds.fds_bits[i];
788 #endif
789 #else
790 for (int32_t i = LWIP_SOCKET_OFFSET / __NFDBITS; i <= epollSetPtr->maxfd / __NFDBITS; i++) {
791 unsigned long bits = (unsigned long)(__FDS_BITS(&(epollSetPtr->exceptfds))[i]);
792 #endif
793 while (bits != 0) {
794 int32_t fd;
795 int32_t bitIdx = RearZeroBitNum(bits);
796 #ifdef __LITEOS__
797 #ifdef FDSETSAFESET
798 fd = i * BYTE_BITS_NUM + bitIdx + LWIP_SOCKET_OFFSET;
799 #else
800 fd = i * NFDBITS + bitIdx;
801 #endif
802 #else
803 fd = i * __NFDBITS + bitIdx;
804 #endif
805 func(epollSetPtr, param, fd);
806 bits &= (bits - 1);
807 }
808 }
809 }
810
811 int32_t EpollLoop(EpollDesc epollfd, int32_t timeout)
812 {
813 EpollSet *epollSetPtr = NULL;
814 fd_set readfds, writefds, exceptfds;
815 EpollSetPtr param = {&readfds, &writefds, &exceptfds};
816 int32_t ret;
817 struct timeval tv;
818 struct timeval *tvp = NULL;
819
820 if (!IsEpollDescValid(epollfd)) {
821 return NSTACKX_EFAILED;
822 }
823
824 if (timeout != -1) {
825 tv.tv_sec = timeout / NSTACKX_MILLI_TICKS;
826 tv.tv_usec = (timeout % NSTACKX_MILLI_TICKS) * NSTACKX_MICRO_SEC_PER_MILLI_SEC;
827 tvp = &tv;
828 }
829
830 epollSetPtr = container_of(epollfd, EpollSet, epollfd);
831 if (memcpy_s(&readfds, sizeof(fd_set), &epollSetPtr->readfds, sizeof(fd_set)) != EOK ||
832 memcpy_s(&writefds, sizeof(fd_set), &epollSetPtr->writefds, sizeof(fd_set)) != EOK ||
833 memcpy_s(&exceptfds, sizeof(fd_set), &epollSetPtr->exceptfds, sizeof(fd_set)) != EOK) {
834 return NSTACKX_EFAILED;
835 }
836
837 ret = select(epollSetPtr->maxfd + 1, &readfds, &writefds, &exceptfds, tvp);
838 if (ret < 0) {
839 if (errno == EINTR) {
840 return NSTACKX_EINTR;
841 }
842 LOGE(TAG, "epoll %d select error", epollfd->recvFd);
843 return NSTACKX_EFAILED;
844 } else if (ret == 0) {
845 return NSTACKX_ETIMEOUT;
846 }
847
848 EpollSetTraverse(epollSetPtr, EpollSetFdHandle, ¶m);
849
850 return ret;
851 }
852
853 #ifndef LWIP_LITEOS_A_COMPAT
854 static void EpollSetClearHandle(EpollSet *epollSetPtr, void *param, int32_t fd)
855 {
856 EpollSet *setPtr = g_epollEventPtrArray[EVENT_PTR_IDX(fd)].epollSetPtr;
857 (void)param;
858 if ((setPtr != NULL) && (setPtr != epollSetPtr)) {
859 LOGE(TAG, "Clear: fd %d ptr has been used", fd);
860 return;
861 }
862 if (pthread_mutex_lock(&g_epollEventPtrMutex) != 0) {
863 LOGE(TAG, "pthread mutex lock error");
864 return;
865 }
866 g_epollEventPtrArray[EVENT_PTR_IDX(fd)].epollSetPtr = NULL;
867 g_epollEventPtrArray[EVENT_PTR_IDX(fd)].taskPtr = NULL;
868 if (pthread_mutex_unlock(&g_epollEventPtrMutex) != 0) {
869 LOGE(TAG, "pthread mutex unlock error");
870 return;
871 }
872 }
873
874 static void EpollEventCleanup(const EpollSet *epollSetPtr)
875 {
876 g_epollEventPtrArray[EVENT_PTR_IDX(epollSetPtr->epollfd.recvFd)].epollSetPtr = NULL;
877 g_epollEventPtrArray[EVENT_PTR_IDX(epollSetPtr->epollfd.recvFd)].taskPtr = NULL;
878 g_epollEventPtrArray[EVENT_PTR_IDX(epollSetPtr->epollfd.sendFd)].epollSetPtr = NULL;
879 g_epollEventPtrArray[EVENT_PTR_IDX(epollSetPtr->epollfd.sendFd)].taskPtr = NULL;
880 }
881 #else
882 static void EpollEventCleanup(const EpollSet *epollSetPtr)
883 {
884 List *pos = NULL;
885 List *tmp = NULL;
886 struct EpollTaskList *taskListPtr = NULL;
887 struct EpollEventPtr *ptr = EpollEventListFind(epollSetPtr);
888 if (ptr == NULL) {
889 return;
890 }
891 ListRemoveNode(&(ptr->list));
892 LIST_FOR_EACH_SAFE(pos, tmp, &(ptr->taskList)) {
893 taskListPtr = container_of(pos, struct EpollTaskList, list);
894 ListRemoveNode(&taskListPtr->list);
895 free(taskListPtr);
896 }
897 free(ptr);
898 }
899 #endif /* LWIP_LITEOS_A_COMPAT */
900
901 void CloseEpollDescInner(EpollDesc epollfd)
902 {
903 EpollSet *epollSetPtr = NULL;
904 if (!(IsEpollDescValid(epollfd))) {
905 return;
906 }
907 epollSetPtr = container_of(epollfd, EpollSet, epollfd);
908 #ifndef LWIP_LITEOS_A_COMPAT
909 EpollSetTraverse(epollSetPtr, EpollSetClearHandle, NULL);
910 #endif /* LWIP_LITEOS_A_COMPAT */
911 if (pthread_mutex_lock(&g_epollEventPtrMutex) != 0) {
912 LOGE(TAG, "pthread mutex lock error");
913 goto FAIL_CLOSE;
914 }
915 EpollEventCleanup(epollSetPtr);
916 if (pthread_mutex_unlock(&g_epollEventPtrMutex) != 0) {
917 LOGE(TAG, "pthread mutex unlock error");
918 }
919 FAIL_CLOSE:
920 close(epollfd->recvFd);
921 close(epollfd->sendFd);
922 if (pthread_mutex_destroy(&(epollSetPtr->mutex)) != 0) {
923 LOGE(TAG, "pthread mutex destroy error: %d", errno);
924 }
925 free(epollSetPtr);
926
927 return;
928 }
929
930 #ifdef LWIP_LITEOS_A_COMPAT
931 static EpollSet *CloseDescEpollHandle(int32_t desc)
932 {
933 return EpollSetFindByFd(desc);
934 }
935 #else
936 static EpollSet *CloseDescEpollHandle(int32_t desc)
937 {
938 EpollSet *epollSetPtr = g_epollEventPtrArray[EVENT_PTR_IDX(desc)].epollSetPtr;
939 g_epollEventPtrArray[EVENT_PTR_IDX(desc)].epollSetPtr = NULL;
940 g_epollEventPtrArray[EVENT_PTR_IDX(desc)].taskPtr = NULL;
941 return epollSetPtr;
942 }
943 #endif
944
945 void CloseDescClearEpollPtr(int32_t desc)
946 {
947 EpollSet *epollSetPtr = NULL;
948 if (IS_INVALID_SOCKET_DESC(desc)) {
949 LOGE(TAG, "invalid socket : %d", desc);
950 return;
951 }
952 if (g_epollInited != NSTACKX_TRUE) {
953 LOGE(TAG, "Epoll Event Ptr Not Init");
954 return;
955 }
956
957 if (pthread_mutex_lock(&g_epollEventPtrMutex) != 0) {
958 LOGE(TAG, "pthread mutex lock error");
959 return;
960 }
961 epollSetPtr = CloseDescEpollHandle(desc);
962 if (pthread_mutex_unlock(&g_epollEventPtrMutex) != 0) {
963 LOGE(TAG, "pthread mutex unlock error");
964 return;
965 }
966
967 if (epollSetPtr == NULL) {
968 return;
969 }
970
971 if (pthread_mutex_lock(&(epollSetPtr->mutex)) != 0) {
972 LOGE(TAG, "pthread mutex lock error");
973 return;
974 }
975 FD_CLR(desc, &epollSetPtr->readfds);
976 FD_CLR(desc, &epollSetPtr->writefds);
977 FD_CLR(desc, &epollSetPtr->exceptfds);
978 if (desc == epollSetPtr->maxfd) {
979 EpollSetMaxFdUpdate(epollSetPtr);
980 }
981 if (pthread_mutex_unlock(&(epollSetPtr->mutex)) != 0) {
982 LOGE(TAG, "pthread mutex unlock error");
983 return;
984 }
985 }
986