OpenVPN
event.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2025 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include "buffer.h"
30#include "error.h"
31#include "integer.h"
32#include "event.h"
33#include "fdmisc.h"
34
35#if EPOLL
36#include <sys/epoll.h>
37#endif
38
39#include "memdbg.h"
40
41/*
42 * Some OSes will prefer select() over poll()
43 * when both are available.
44 */
45#if defined(TARGET_DARWIN)
46#define SELECT_PREFERRED_OVER_POLL
47#endif
48
49/*
50 * All non-windows OSes are assumed to have select()
51 */
52#ifdef _WIN32
53#define SELECT 0
54#else
55#define SELECT 1
56#endif
57
58/*
59 * This should be set to the highest file descriptor
60 * which can be used in one of the FD_ macros.
61 */
62#ifdef FD_SETSIZE
63#define SELECT_MAX_FDS FD_SETSIZE
64#else
65#define SELECT_MAX_FDS 256
66#endif
67
68static inline int
69tv_to_ms_timeout(const struct timeval *tv)
70{
71 if (tv->tv_sec == 0 && tv->tv_usec == 0)
72 {
73 return 0;
74 }
75 else
76 {
77 return max_int(tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000, 1);
78 }
79}
80
81#ifdef _WIN32
82
83struct we_set
84{
86 bool fast;
87 HANDLE *events;
91};
92
93static inline void
94we_set_event(struct we_set *wes, int i, event_t event, unsigned int rwflags, void *arg)
95{
96 ASSERT(i >= 0 && i < wes->capacity);
97
98 if (rwflags == EVENT_READ)
99 {
100 ASSERT(event->read != NULL);
101 wes->events[i] = event->read;
102 }
103 else if (rwflags == EVENT_WRITE)
104 {
105 ASSERT(event->write != NULL);
106 wes->events[i] = event->write;
107 }
108 else
109 {
110 msg(M_FATAL, "fatal error in we_set_events: rwflags=%d", rwflags);
111 }
112
113 wes->esr[i].rwflags = rwflags;
114 wes->esr[i].arg = arg;
115}
116
117static inline bool
118we_append_event(struct we_set *wes, event_t event, unsigned int rwflags, void *arg)
119{
120 if (rwflags & EVENT_WRITE)
121 {
122 if (wes->n_events < wes->capacity)
123 {
124 we_set_event(wes, wes->n_events, event, EVENT_WRITE, arg);
125 ++wes->n_events;
126 }
127 else
128 {
129 return false;
130 }
131 }
132 if (rwflags & EVENT_READ)
133 {
134 if (wes->n_events < wes->capacity)
135 {
136 we_set_event(wes, wes->n_events, event, EVENT_READ, arg);
137 ++wes->n_events;
138 }
139 else
140 {
141 return false;
142 }
143 }
144 return true;
145}
146
147static void
148we_del_event(struct we_set *wes, event_t event)
149{
150 int i, j = 0;
151 const int len = wes->n_events;
152
153 for (i = 0; i < len; ++i)
154 {
155 const HANDLE h = wes->events[i];
156 if (h == event->read || h == event->write)
157 {
158 --wes->n_events;
159 }
160 else
161 {
162 if (i != j)
163 {
164 wes->events[j] = wes->events[i];
165 wes->esr[j] = wes->esr[i];
166 }
167 ++j;
168 }
169 }
170}
171
172static void
173we_del_index(struct we_set *wes, int index)
174{
175 int i;
176 ASSERT(index >= 0 && index < wes->n_events);
177 for (i = index; i < wes->n_events - 1; ++i)
178 {
179 wes->events[i] = wes->events[i + 1];
180 wes->esr[i] = wes->esr[i + 1];
181 }
182 --wes->n_events;
183}
184
185static void
186we_get_rw_indices(struct we_set *wes, event_t event, int *ri, int *wi)
187{
188 int i;
189 *ri = *wi = -1;
190 for (i = 0; i < wes->n_events; ++i)
191 {
192 const HANDLE h = wes->events[i];
193 if (h == event->read)
194 {
195 ASSERT(*ri == -1);
196 *ri = i;
197 }
198 else if (h == event->write)
199 {
200 ASSERT(*wi == -1);
201 *wi = i;
202 }
203 }
204}
205
206static void
208{
209 struct we_set *wes = (struct we_set *)es;
210 free(wes->events);
211 free(wes->esr);
212 free(wes);
213}
214
215static void
217{
218 struct we_set *wes = (struct we_set *)es;
219 ASSERT(wes->fast);
220 wes->n_events = 0;
221}
222
223static void
224we_del(struct event_set *es, event_t event)
225{
226 struct we_set *wes = (struct we_set *)es;
227 ASSERT(!wes->fast);
228 we_del_event(wes, event);
229}
230
231static void
232we_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
233{
234 struct we_set *wes = (struct we_set *)es;
235
236 dmsg(D_EVENT_WAIT, "WE_CTL n=%d ev=%p rwflags=0x%04x arg=" ptr_format, wes->n_events, event,
237 rwflags, (ptr_type)arg);
238
239 if (wes->fast)
240 {
241 if (!we_append_event(wes, event, rwflags, arg))
242 {
243 goto err;
244 }
245 }
246 else
247 {
248 int ri, wi;
249 int one = -1;
250 int n = 0;
251
252 we_get_rw_indices(wes, event, &ri, &wi);
253 if (wi >= 0)
254 {
255 one = wi;
256 ++n;
257 }
258 if (ri >= 0)
259 {
260 one = ri;
261 ++n;
262 }
263 switch (rwflags)
264 {
265 case 0:
266 switch (n)
267 {
268 case 0:
269 break;
270
271 case 1:
272 we_del_index(wes, one);
273 break;
274
275 case 2:
276 we_del_event(wes, event);
277 break;
278
279 default:
280 ASSERT(0);
281 }
282 break;
283
284 case EVENT_READ:
285 switch (n)
286 {
287 case 0:
288 if (!we_append_event(wes, event, EVENT_READ, arg))
289 {
290 goto err;
291 }
292 break;
293
294 case 1:
295 we_set_event(wes, one, event, EVENT_READ, arg);
296 break;
297
298 case 2:
299 we_del_index(wes, wi);
300 break;
301
302 default:
303 ASSERT(0);
304 }
305 break;
306
307 case EVENT_WRITE:
308 switch (n)
309 {
310 case 0:
311 if (!we_append_event(wes, event, EVENT_WRITE, arg))
312 {
313 goto err;
314 }
315 break;
316
317 case 1:
318 we_set_event(wes, one, event, EVENT_WRITE, arg);
319 break;
320
321 case 2:
322 we_del_index(wes, ri);
323 break;
324
325 default:
326 ASSERT(0);
327 }
328 break;
329
330 case EVENT_READ | EVENT_WRITE:
331 switch (n)
332 {
333 case 0:
334 if (!we_append_event(wes, event, EVENT_READ | EVENT_WRITE, arg))
335 {
336 goto err;
337 }
338 break;
339
340 case 1:
341 if (ri == -1)
342 {
343 ASSERT(wi != -1);
344 if (!we_append_event(wes, event, EVENT_READ, arg))
345 {
346 goto err;
347 }
348 }
349 else if (wi == -1)
350 {
351 if (!we_append_event(wes, event, EVENT_WRITE, arg))
352 {
353 goto err;
354 }
355 }
356 else
357 {
358 ASSERT(0);
359 }
360 break;
361
362 case 2:
363 break;
364
365 default:
366 ASSERT(0);
367 }
368 break;
369
370 default:
371 msg(M_FATAL, "fatal error in we_ctl: rwflags=%d", rwflags);
372 }
373 }
374 return;
375
376err:
378 "Error: Windows resource limit WSA_MAXIMUM_WAIT_EVENTS (%d) has been exceeded",
379 WSA_MAXIMUM_WAIT_EVENTS);
380}
381
382static int
383we_wait(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
384{
385 struct we_set *wes = (struct we_set *)es;
386 const int timeout = tv_to_ms_timeout(tv);
387 DWORD status;
388
389 dmsg(D_EVENT_WAIT, "WE_WAIT enter n=%d to=%d", wes->n_events, timeout);
390
391#ifdef ENABLE_DEBUG
393 {
394 int i;
395 for (i = 0; i < wes->n_events; ++i)
396 {
397 dmsg(D_EVENT_WAIT, "[%d] ev=%p rwflags=0x%04x arg=" ptr_format, i, wes->events[i],
398 wes->esr[i].rwflags, (ptr_type)wes->esr[i].arg);
399 }
400 }
401#endif
402
403 /*
404 * First poll our event list with 0 timeout
405 */
406 status = WSAWaitForMultipleEvents((DWORD)wes->n_events, wes->events, FALSE, (DWORD)0, FALSE);
407
408 /*
409 * If at least one event is already set, we must
410 * individually poll the whole list.
411 */
412 if (status >= WSA_WAIT_EVENT_0 && status < WSA_WAIT_EVENT_0 + (DWORD)wes->n_events)
413 {
414 int i;
415 int j = 0;
416 for (i = 0; i < wes->n_events; ++i)
417 {
418 if (j >= outlen)
419 {
420 break;
421 }
422 if (WaitForSingleObject(wes->events[i], 0) == WAIT_OBJECT_0)
423 {
424 *out = wes->esr[i];
425 dmsg(D_EVENT_WAIT, "WE_WAIT leave [%d,%d] rwflags=0x%04x arg=" ptr_format, i, j,
426 out->rwflags, (ptr_type)out->arg);
427 ++j;
428 ++out;
429 }
430 }
431 return j;
432 }
433 else
434 {
435 /*
436 * If caller specified timeout > 0, we know at this point
437 * that no events are set, so wait only for the first event
438 * (or timeout) and return at most one event_set_return object.
439 *
440 * If caller specified timeout == 0, the second call to
441 * WSAWaitForMultipleEvents would be redundant -- just
442 * return 0 indicating timeout.
443 */
444 if (timeout > 0)
445 {
446 status = WSAWaitForMultipleEvents((DWORD)wes->n_events, wes->events, FALSE,
447 (DWORD)timeout, FALSE);
448 }
449
450 if (outlen >= 1 && status >= WSA_WAIT_EVENT_0
451 && status < WSA_WAIT_EVENT_0 + (DWORD)wes->n_events)
452 {
453 *out = wes->esr[status - WSA_WAIT_EVENT_0];
454 dmsg(D_EVENT_WAIT, "WE_WAIT leave rwflags=0x%04x arg=" ptr_format, out->rwflags,
455 (ptr_type)out->arg);
456 return 1;
457 }
458 else if (status == WSA_WAIT_TIMEOUT)
459 {
460 return 0;
461 }
462 else
463 {
464 return -1;
465 }
466 }
467}
468
469static struct event_set *
470we_init(int *maxevents, unsigned int flags)
471{
472 struct we_set *wes;
473
474 dmsg(D_EVENT_WAIT, "WE_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
475
476 ALLOC_OBJ_CLEAR(wes, struct we_set);
477
478 /* set dispatch functions */
479 wes->func.free = we_free;
480 wes->func.reset = we_reset;
481 wes->func.del = we_del;
482 wes->func.ctl = we_ctl;
483 wes->func.wait = we_wait;
484
485 if (flags & EVENT_METHOD_FAST)
486 {
487 wes->fast = true;
488 }
489 wes->n_events = 0;
490
491 /* Figure our event capacity */
492 ASSERT(*maxevents > 0);
493 wes->capacity = min_int(*maxevents * 2, WSA_MAXIMUM_WAIT_EVENTS);
494 *maxevents = min_int(*maxevents, WSA_MAXIMUM_WAIT_EVENTS);
495
496 /* Allocate space for Win32 event handles */
497 ALLOC_ARRAY_CLEAR(wes->events, HANDLE, wes->capacity);
498
499 /* Allocate space for event_set_return objects */
501
502 dmsg(D_EVENT_WAIT, "WE_INIT maxevents=%d capacity=%d", *maxevents, wes->capacity);
503
504 return (struct event_set *)wes;
505}
506
507#endif /* _WIN32 */
508
509#if EPOLL
510
511struct ep_set
512{
513 struct event_set_functions func;
514 bool fast;
515 int epfd;
516 int maxevents;
517 struct epoll_event *events;
518};
519
520static void
521ep_free(struct event_set *es)
522{
523 struct ep_set *eps = (struct ep_set *)es;
524 close(eps->epfd);
525 free(eps->events);
526 free(eps);
527}
528
529static void
530ep_reset(struct event_set *es)
531{
532 const struct ep_set *eps = (struct ep_set *)es;
533 ASSERT(eps->fast);
534}
535
536static void
537ep_del(struct event_set *es, event_t event)
538{
539 struct epoll_event ev;
540 struct ep_set *eps = (struct ep_set *)es;
541
542 dmsg(D_EVENT_WAIT, "EP_DEL ev=%d", (int)event);
543
544 ASSERT(!eps->fast);
545 CLEAR(ev);
546 if (epoll_ctl(eps->epfd, EPOLL_CTL_DEL, event, &ev) < 0)
547 {
548 msg(M_WARN | M_ERRNO, "EVENT: epoll_ctl EPOLL_CTL_DEL failed, sd=%d", (int)event);
549 }
550}
551
552static void
553ep_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
554{
555 struct ep_set *eps = (struct ep_set *)es;
556 struct epoll_event ev;
557
558 CLEAR(ev);
559
560 ev.data.ptr = arg;
561 if (rwflags & EVENT_READ)
562 {
563 ev.events |= EPOLLIN;
564 }
565 if (rwflags & EVENT_WRITE)
566 {
567 ev.events |= EPOLLOUT;
568 }
569
570 dmsg(D_EVENT_WAIT, "EP_CTL fd=%d rwflags=0x%04x ev=0x%08x arg=" ptr_format, (int)event, rwflags,
571 (unsigned int)ev.events, (ptr_type)ev.data.ptr);
572
573 if (epoll_ctl(eps->epfd, EPOLL_CTL_MOD, event, &ev) < 0)
574 {
575 if (errno == ENOENT)
576 {
577 if (epoll_ctl(eps->epfd, EPOLL_CTL_ADD, event, &ev) < 0)
578 {
579 msg(M_ERR, "EVENT: epoll_ctl EPOLL_CTL_ADD failed, sd=%d", (int)event);
580 }
581 }
582 else
583 {
584 msg(M_ERR, "EVENT: epoll_ctl EPOLL_CTL_MOD failed, sd=%d", (int)event);
585 }
586 }
587}
588
589static int
590ep_wait(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
591{
592 struct ep_set *eps = (struct ep_set *)es;
593 int stat;
594
595 if (outlen > eps->maxevents)
596 {
597 outlen = eps->maxevents;
598 }
599
600 stat = epoll_wait(eps->epfd, eps->events, outlen, tv_to_ms_timeout(tv));
601 ASSERT(stat <= outlen);
602
603 if (stat > 0)
604 {
605 int i;
606 const struct epoll_event *ev = eps->events;
607 struct event_set_return *esr = out;
608 for (i = 0; i < stat; ++i)
609 {
610 esr->rwflags = 0;
611 if (ev->events & (EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP))
612 {
613 esr->rwflags |= EVENT_READ;
614 }
615 if (ev->events & EPOLLOUT)
616 {
617 esr->rwflags |= EVENT_WRITE;
618 }
619 esr->arg = ev->data.ptr;
620 dmsg(D_EVENT_WAIT, "EP_WAIT[%d] rwflags=0x%04x ev=0x%08x arg=" ptr_format, i,
621 esr->rwflags, ev->events, (ptr_type)ev->data.ptr);
622 ++ev;
623 ++esr;
624 }
625 }
626 return stat;
627}
628
629static struct event_set *
630ep_init(int *maxevents, unsigned int flags)
631{
632 struct ep_set *eps;
633 int fd;
634
635 dmsg(D_EVENT_WAIT, "EP_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
636
637 /* open epoll file descriptor */
638 fd = epoll_create(*maxevents);
639 if (fd < 0)
640 {
641 return NULL;
642 }
643
644 set_cloexec(fd);
645
646 ALLOC_OBJ_CLEAR(eps, struct ep_set);
647
648 /* set dispatch functions */
649 eps->func.free = ep_free;
650 eps->func.reset = ep_reset;
651 eps->func.del = ep_del;
652 eps->func.ctl = ep_ctl;
653 eps->func.wait = ep_wait;
654
655 /* fast method ("sort of") corresponds to epoll one-shot */
656 if (flags & EVENT_METHOD_FAST)
657 {
658 eps->fast = true;
659 }
660
661 /* allocate space for epoll_wait return */
662 ASSERT(*maxevents > 0);
663 eps->maxevents = *maxevents;
664 ALLOC_ARRAY_CLEAR(eps->events, struct epoll_event, eps->maxevents);
665
666 /* set epoll control fd */
667 eps->epfd = fd;
668
669 return (struct event_set *)eps;
670}
671#endif /* EPOLL */
672
673#if POLL
674
675struct po_set
676{
677 struct event_set_functions func;
678 bool fast;
679 struct pollfd *events;
680 void **args;
681 int n_events;
682 int capacity;
683};
684
685static void
686po_free(struct event_set *es)
687{
688 struct po_set *pos = (struct po_set *)es;
689 free(pos->events);
690 free(pos->args);
691 free(pos);
692}
693
694static void
695po_reset(struct event_set *es)
696{
697 struct po_set *pos = (struct po_set *)es;
698 ASSERT(pos->fast);
699 pos->n_events = 0;
700}
701
702static void
703po_del(struct event_set *es, event_t event)
704{
705 struct po_set *pos = (struct po_set *)es;
706 int i;
707
708 dmsg(D_EVENT_WAIT, "PO_DEL ev=%d", (int)event);
709
710 ASSERT(!pos->fast);
711 for (i = 0; i < pos->n_events; ++i)
712 {
713 if (pos->events[i].fd == event)
714 {
715 int j;
716 for (j = i; j < pos->n_events - 1; ++j)
717 {
718 pos->events[j] = pos->events[j + 1];
719 pos->args[j] = pos->args[j + 1];
720 }
721 --pos->n_events;
722 break;
723 }
724 }
725}
726
727static inline void
728po_set_pollfd_events(struct pollfd *pfdp, unsigned int rwflags)
729{
730 pfdp->events = 0;
731 if (rwflags & EVENT_WRITE)
732 {
733 pfdp->events |= POLLOUT;
734 }
735 if (rwflags & EVENT_READ)
736 {
737 pfdp->events |= (POLLIN | POLLPRI);
738 }
739}
740
741static inline bool
742po_append_event(struct po_set *pos, event_t event, unsigned int rwflags, void *arg)
743{
744 if (pos->n_events < pos->capacity)
745 {
746 struct pollfd *pfdp = &pos->events[pos->n_events];
747 pfdp->fd = event;
748 pos->args[pos->n_events] = arg;
749 po_set_pollfd_events(pfdp, rwflags);
750 ++pos->n_events;
751 return true;
752 }
753 else
754 {
755 return false;
756 }
757}
758
759static void
760po_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
761{
762 struct po_set *pos = (struct po_set *)es;
763
764 dmsg(D_EVENT_WAIT, "PO_CTL rwflags=0x%04x ev=%d arg=" ptr_format, rwflags, (int)event,
765 (ptr_type)arg);
766
767 if (pos->fast)
768 {
769 if (!po_append_event(pos, event, rwflags, arg))
770 {
771 goto err;
772 }
773 }
774 else
775 {
776 int i;
777 for (i = 0; i < pos->n_events; ++i)
778 {
779 struct pollfd *pfdp = &pos->events[i];
780 if (pfdp->fd == event)
781 {
782 pos->args[i] = arg;
783 po_set_pollfd_events(pfdp, rwflags);
784 goto done;
785 }
786 }
787 if (!po_append_event(pos, event, rwflags, arg))
788 {
789 goto err;
790 }
791 }
792
793done:
794 return;
795
796err:
797 msg(D_EVENT_ERRORS, "Error: poll: too many I/O wait events");
798}
799
800static int
801po_wait(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
802{
803 struct po_set *pos = (struct po_set *)es;
804 int stat;
805
806 stat = poll(pos->events, pos->n_events, tv_to_ms_timeout(tv));
807
808 ASSERT(stat <= pos->n_events);
809
810 if (stat > 0)
811 {
812 int i, j = 0;
813 const struct pollfd *pfdp = pos->events;
814 for (i = 0; i < pos->n_events && j < outlen; ++i)
815 {
816 if (pfdp->revents & (POLLIN | POLLPRI | POLLERR | POLLHUP | POLLOUT))
817 {
818 out->rwflags = 0;
819 if (pfdp->revents & (POLLIN | POLLPRI | POLLERR | POLLHUP))
820 {
821 out->rwflags |= EVENT_READ;
822 }
823 if (pfdp->revents & POLLOUT)
824 {
825 out->rwflags |= EVENT_WRITE;
826 }
827 out->arg = pos->args[i];
829 "PO_WAIT[%d,%d] fd=%d rev=0x%08x rwflags=0x%04x arg=" ptr_format " %s", i, j,
830 pfdp->fd, pfdp->revents, out->rwflags, (ptr_type)out->arg,
831 pos->fast ? "" : "[scalable]");
832 ++out;
833 ++j;
834 }
835 else if (pfdp->revents)
836 {
837 msg(D_EVENT_ERRORS, "Error: poll: unknown revents=0x%04x for fd=%d",
838 (unsigned int)pfdp->revents, pfdp->fd);
839 }
840 ++pfdp;
841 }
842 return j;
843 }
844 return stat;
845}
846
847static struct event_set *
848po_init(int *maxevents, unsigned int flags)
849{
850 struct po_set *pos;
851
852 dmsg(D_EVENT_WAIT, "PO_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
853
854 ALLOC_OBJ_CLEAR(pos, struct po_set);
855
856 /* set dispatch functions */
857 pos->func.free = po_free;
858 pos->func.reset = po_reset;
859 pos->func.del = po_del;
860 pos->func.ctl = po_ctl;
861 pos->func.wait = po_wait;
862
863 if (flags & EVENT_METHOD_FAST)
864 {
865 pos->fast = true;
866 }
867
868 pos->n_events = 0;
869
870 /* Figure our event capacity */
871 ASSERT(*maxevents > 0);
872 pos->capacity = *maxevents;
873
874 /* Allocate space for pollfd structures to be passed to poll() */
875 ALLOC_ARRAY_CLEAR(pos->events, struct pollfd, pos->capacity);
876
877 /* Allocate space for event_set_return objects */
878 ALLOC_ARRAY_CLEAR(pos->args, void *, pos->capacity);
879
880 return (struct event_set *)pos;
881}
882#endif /* POLL */
883
884#if SELECT
885
886struct se_set
887{
888 struct event_set_functions func;
889 bool fast;
890 fd_set readfds;
891 fd_set writefds;
892 void **args; /* allocated to capacity size */
893 int maxfd; /* largest fd seen so far, always < capacity */
894 int capacity; /* fixed largest fd + 1 */
895};
896
897static void
898se_free(struct event_set *es)
899{
900 struct se_set *ses = (struct se_set *)es;
901 free(ses->args);
902 free(ses);
903}
904
905static void
906se_reset(struct event_set *es)
907{
908 struct se_set *ses = (struct se_set *)es;
909 int i;
910 ASSERT(ses->fast);
911
912 dmsg(D_EVENT_WAIT, "SE_RESET");
913
914 FD_ZERO(&ses->readfds);
915 FD_ZERO(&ses->writefds);
916 for (i = 0; i <= ses->maxfd; ++i)
917 {
918 ses->args[i] = NULL;
919 }
920 ses->maxfd = -1;
921}
922
923static void
924se_del(struct event_set *es, event_t event)
925{
926 struct se_set *ses = (struct se_set *)es;
927 ASSERT(!ses->fast);
928
929 dmsg(D_EVENT_WAIT, "SE_DEL ev=%d", (int)event);
930
931 if (event >= 0 && event < ses->capacity)
932 {
933 FD_CLR(event, &ses->readfds);
934 FD_CLR(event, &ses->writefds);
935 ses->args[event] = NULL;
936 }
937 else
938 {
939 msg(D_EVENT_ERRORS, "Error: select/se_del: too many I/O wait events");
940 }
941 return;
942}
943
944static void
945se_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
946{
947 struct se_set *ses = (struct se_set *)es;
948
949 dmsg(D_EVENT_WAIT, "SE_CTL rwflags=0x%04x ev=%d fast=%d cap=%d maxfd=%d arg=" ptr_format,
950 rwflags, (int)event, (int)ses->fast, ses->capacity, ses->maxfd, (ptr_type)arg);
951
952 if (event >= 0 && event < ses->capacity)
953 {
954 ses->maxfd = max_int(event, ses->maxfd);
955 ses->args[event] = arg;
956 if (ses->fast)
957 {
958 if (rwflags & EVENT_READ)
959 {
960 openvpn_fd_set(event, &ses->readfds);
961 }
962 if (rwflags & EVENT_WRITE)
963 {
964 openvpn_fd_set(event, &ses->writefds);
965 }
966 }
967 else
968 {
969 if (rwflags & EVENT_READ)
970 {
971 openvpn_fd_set(event, &ses->readfds);
972 }
973 else
974 {
975 FD_CLR(event, &ses->readfds);
976 }
977 if (rwflags & EVENT_WRITE)
978 {
979 openvpn_fd_set(event, &ses->writefds);
980 }
981 else
982 {
983 FD_CLR(event, &ses->writefds);
984 }
985 }
986 }
987 else
988 {
989 msg(D_EVENT_ERRORS, "Error: select: too many I/O wait events, fd=%d cap=%d", (int)event,
990 ses->capacity);
991 }
992}
993
994static int
995se_wait_return(struct se_set *ses, fd_set *read, fd_set *write, struct event_set_return *out,
996 int outlen)
997{
998 int i, j = 0;
999 for (i = 0; i <= ses->maxfd && j < outlen; ++i)
1000 {
1001 const bool r = FD_ISSET(i, read);
1002 const bool w = FD_ISSET(i, write);
1003 if (r || w)
1004 {
1005 out->rwflags = 0;
1006 if (r)
1007 {
1008 out->rwflags |= EVENT_READ;
1009 }
1010 if (w)
1011 {
1012 out->rwflags |= EVENT_WRITE;
1013 }
1014 out->arg = ses->args[i];
1015 dmsg(D_EVENT_WAIT, "SE_WAIT[%d,%d] rwflags=0x%04x arg=" ptr_format, i, j, out->rwflags,
1016 (ptr_type)out->arg);
1017 ++out;
1018 ++j;
1019 }
1020 }
1021 return j;
1022}
1023
1024static int
1025se_wait_fast(struct event_set *es, const struct timeval *tv, struct event_set_return *out,
1026 int outlen)
1027{
1028 struct se_set *ses = (struct se_set *)es;
1029 struct timeval tv_tmp = *tv;
1030 int stat;
1031
1032 dmsg(D_EVENT_WAIT, "SE_WAIT_FAST maxfd=%d tv=%" PRIi64 "/%ld", ses->maxfd,
1033 (int64_t)tv_tmp.tv_sec, (long)tv_tmp.tv_usec);
1034
1035 stat = select(ses->maxfd + 1, &ses->readfds, &ses->writefds, NULL, &tv_tmp);
1036
1037 if (stat > 0)
1038 {
1039 stat = se_wait_return(ses, &ses->readfds, &ses->writefds, out, outlen);
1040 }
1041
1042 return stat;
1043}
1044
1045static int
1046se_wait_scalable(struct event_set *es, const struct timeval *tv, struct event_set_return *out,
1047 int outlen)
1048{
1049 struct se_set *ses = (struct se_set *)es;
1050 struct timeval tv_tmp = *tv;
1051 fd_set read = ses->readfds;
1052 fd_set write = ses->writefds;
1053 int stat;
1054
1055 dmsg(D_EVENT_WAIT, "SE_WAIT_SCALEABLE maxfd=%d tv=%" PRIi64 "/%ld", ses->maxfd,
1056 (int64_t)tv_tmp.tv_sec, (long)tv_tmp.tv_usec);
1057
1058 stat = select(ses->maxfd + 1, &read, &write, NULL, &tv_tmp);
1059
1060 if (stat > 0)
1061 {
1062 stat = se_wait_return(ses, &read, &write, out, outlen);
1063 }
1064
1065 return stat;
1066}
1067
1068static struct event_set *
1069se_init(int *maxevents, unsigned int flags)
1070{
1071 struct se_set *ses;
1072
1073 dmsg(D_EVENT_WAIT, "SE_INIT maxevents=%d flags=0x%08x", *maxevents, flags);
1074
1075 ALLOC_OBJ_CLEAR(ses, struct se_set);
1076
1077 /* set dispatch functions */
1078 ses->func.free = se_free;
1079 ses->func.reset = se_reset;
1080 ses->func.del = se_del;
1081 ses->func.ctl = se_ctl;
1082 ses->func.wait = se_wait_scalable;
1083
1084 if (flags & EVENT_METHOD_FAST)
1085 {
1086 ses->fast = true;
1087 ses->func.wait = se_wait_fast;
1088 }
1089
1090 /* Select needs to be passed this value + 1 */
1091 ses->maxfd = -1;
1092
1093 /* Set our event capacity */
1094 ASSERT(*maxevents > 0);
1095 *maxevents = min_int(*maxevents, SELECT_MAX_FDS);
1096 ses->capacity = SELECT_MAX_FDS;
1097
1098 /* Allocate space for event_set_return void * args */
1099 ALLOC_ARRAY_CLEAR(ses->args, void *, ses->capacity);
1100
1101 return (struct event_set *)ses;
1102}
1103#endif /* SELECT */
1104
1105static struct event_set *
1106event_set_init_simple(int *maxevents, unsigned int flags)
1107{
1108 struct event_set *ret = NULL;
1109#ifdef _WIN32
1110 ret = we_init(maxevents, flags);
1111#elif POLL && SELECT
1112#if 0 /* Define to 1 if EVENT_METHOD_US_TIMEOUT should cause select to be favored over poll */
1113 if (flags & EVENT_METHOD_US_TIMEOUT)
1114 {
1115 ret = se_init(maxevents, flags);
1116 }
1117#endif
1118#ifdef SELECT_PREFERRED_OVER_POLL
1119 if (!ret)
1120 {
1121 ret = se_init(maxevents, flags);
1122 }
1123 if (!ret)
1124 {
1125 ret = po_init(maxevents, flags);
1126 }
1127#else /* ifdef SELECT_PREFERRED_OVER_POLL */
1128 if (!ret)
1129 {
1130 ret = po_init(maxevents, flags);
1131 }
1132 if (!ret)
1133 {
1134 ret = se_init(maxevents, flags);
1135 }
1136#endif
1137#elif POLL
1138 ret = po_init(maxevents, flags);
1139#elif SELECT
1140 ret = se_init(maxevents, flags);
1141#else /* ifdef _WIN32 */
1142#error At least one of poll, select, or WSAWaitForMultipleEvents must be supported by the kernel
1143#endif /* ifdef _WIN32 */
1144 ASSERT(ret);
1145 return ret;
1146}
1147
1148static struct event_set *
1149event_set_init_scalable(int *maxevents, unsigned int flags)
1150{
1151 struct event_set *ret = NULL;
1152#if EPOLL
1153 ret = ep_init(maxevents, flags);
1154 if (!ret)
1155 {
1156 msg(M_WARN, "Note: sys_epoll API is unavailable, falling back to poll/select API");
1157 ret = event_set_init_simple(maxevents, flags);
1158 }
1159#else /* if EPOLL */
1160 ret = event_set_init_simple(maxevents, flags);
1161#endif
1162 ASSERT(ret);
1163 return ret;
1164}
1165
1166struct event_set *
1167event_set_init(int *maxevents, unsigned int flags)
1168{
1169 if (flags & EVENT_METHOD_FAST)
1170 {
1171 return event_set_init_simple(maxevents, flags);
1172 }
1173 else
1174 {
1175 return event_set_init_scalable(maxevents, flags);
1176 }
1177}
#define ALLOC_ARRAY_CLEAR(dptr, type, n)
Definition buffer.h:1058
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition buffer.h:1042
unsigned long ptr_type
Definition common.h:57
#define ptr_format
Definition common.h:48
#define D_EVENT_ERRORS
Definition errlevel.h:65
#define D_EVENT_WAIT
Definition errlevel.h:161
static bool we_append_event(struct we_set *wes, event_t event, unsigned int rwflags, void *arg)
Definition event.c:118
#define SELECT_MAX_FDS
Definition event.c:65
static struct event_set * event_set_init_simple(int *maxevents, unsigned int flags)
Definition event.c:1106
static void we_free(struct event_set *es)
Definition event.c:207
static void we_get_rw_indices(struct we_set *wes, event_t event, int *ri, int *wi)
Definition event.c:186
static void we_del_index(struct we_set *wes, int index)
Definition event.c:173
static int tv_to_ms_timeout(const struct timeval *tv)
Definition event.c:69
static struct event_set * event_set_init_scalable(int *maxevents, unsigned int flags)
Definition event.c:1149
static void we_del(struct event_set *es, event_t event)
Definition event.c:224
static int we_wait(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
Definition event.c:383
static void we_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
Definition event.c:232
static struct event_set * we_init(int *maxevents, unsigned int flags)
Definition event.c:470
struct event_set * event_set_init(int *maxevents, unsigned int flags)
Definition event.c:1167
static void we_del_event(struct we_set *wes, event_t event)
Definition event.c:148
static void we_set_event(struct we_set *wes, int i, event_t event, unsigned int rwflags, void *arg)
Definition event.c:94
static void we_reset(struct event_set *es)
Definition event.c:216
#define EVENT_METHOD_FAST
Definition event.h:82
#define EVENT_METHOD_US_TIMEOUT
Definition event.h:81
#define EVENT_WRITE
Definition event.h:39
#define EVENT_READ
Definition event.h:38
void set_cloexec(socket_descriptor_t fd)
Definition fdmisc.c:78
static void openvpn_fd_set(socket_descriptor_t fd, fd_set *setp)
Definition fdmisc.h:39
static int min_int(int x, int y)
Definition integer.h:105
static int max_int(int x, int y)
Definition integer.h:92
static SERVICE_STATUS status
Definition interactive.c:51
@ write
@ read
#define CLEAR(x)
Definition basic.h:32
#define M_FATAL
Definition error.h:88
static bool check_debug_level(unsigned int level)
Definition error.h:257
#define dmsg(flags,...)
Definition error.h:170
#define M_ERR
Definition error.h:104
#define msg(flags,...)
Definition error.h:150
#define ASSERT(x)
Definition error.h:217
#define M_WARN
Definition error.h:90
#define M_ERRNO
Definition error.h:93
static int pos(char c)
Definition base64.c:104
void(* ctl)(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
Definition event.h:112
int(* wait)(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
Definition event.h:120
void(* del)(struct event_set *es, event_t event)
Definition event.h:111
void(* reset)(struct event_set *es)
Definition event.h:110
void(* free)(struct event_set *es)
Definition event.h:109
unsigned int rwflags
Definition event.h:126
HANDLE write
Definition win32.h:82
HANDLE read
Definition win32.h:81
Definition event.c:84
struct event_set_return * esr
Definition event.c:88
struct event_set_functions func
Definition event.c:85
int capacity
Definition event.c:90
HANDLE * events
Definition event.c:87
bool fast
Definition event.c:86
int n_events
Definition event.c:89
struct env_set * es