Coverage Report

Created: 2026-01-09 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rtpproxy/src/rtpp_epoll.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2022 Sippy Software, Inc., http://www.sippysoft.com
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
 * SUCH DAMAGE.
25
 *
26
 */
27
28
#include "config.h"
29
30
#if HAVE_KQUEUE
31
#include <sys/types.h>
32
#include <sys/event.h>
33
#else
34
#include <sys/epoll.h>
35
#endif
36
#include <assert.h>
37
#include <stdint.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <time.h>
41
42
#include "rtpp_epoll.h"
43
#include "rtpp_debug.h"
44
45
int
46
rtpp_epoll_create()
47
4
{
48
#if HAVE_KQUEUE
49
    int qid = kqueue();
50
51
    return (qid);
52
#else
53
4
    return (epoll_create(1));
54
4
#endif
55
4
}
56
57
int
58
rtpp_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
59
187k
{
60
#if HAVE_KQUEUE
61
    struct kevent k_event;
62
    void *udata;
63
64
    if (op == EPOLL_CTL_DEL) {
65
        EV_SET(&k_event, fd, EVFILT_READ, op, 0, 0, NULL);
66
        int r1 = kevent(epfd, &k_event, 1, NULL, 0, NULL);
67
#if 0
68
        EV_SET(&k_event, fd, EVFILT_WRITE, op, 0, 0, NULL);
69
        int r2 = kevent(epfd, &k_event, 1, NULL, 0, NULL);
70
        return (r1 == 0 || r2 == 0) ? 0 : -1;
71
#endif
72
        return (r1);
73
    }
74
75
    udata = event->data.ptr;
76
    if (event->events & EPOLLIN) {
77
        EV_SET(&k_event, fd, EVFILT_READ, op, 0, 0, udata);
78
        if (kevent(epfd, &k_event, 1, NULL, 0, NULL) != 0)
79
            return (-1);
80
        return (0);
81
    }
82
#if 0
83
    if (event->events & EPOLLOUT) {
84
        EV_SET(&k_event, fd, EVFILT_WRITE, op, 0, 0, udata);
85
        if (kevent(epfd, &k_event, 1, NULL, 0, NULL) != 0)
86
            return (-1);
87
    }
88
#endif
89
    return (-1);
90
#else
91
187k
    return (epoll_ctl(epfd, op, fd, event));
92
187k
#endif
93
187k
}
94
95
#if HAVE_KQUEUE
96
static int
97
append_kevent(struct epoll_event *events, int alloclen, const struct kevent *kep, int i)
98
{
99
    int j;
100
101
    for (j = 0; j < alloclen; j++) {
102
        if (kep[j].ident == kep[i].ident)
103
            break;
104
    }
105
    if (j == alloclen) {
106
        memset(&events[j], '\0', sizeof(events[j]));
107
        events[j].data.ptr = kep[i].udata;
108
    } else {
109
        RTPP_DBG_ASSERT(events[j].data.ptr == kep[i].udata);
110
    }
111
    switch (kep[i].filter) {
112
    case EVFILT_READ:
113
        events[j].events |= EPOLLIN;
114
        break;
115
116
#if 0
117
    case EVFILT_WRITE:
118
        events[j].events |= EPOLLOUT;
119
        break;
120
#endif
121
122
    default:
123
        abort();
124
    }
125
    return (j < alloclen ? alloclen : alloclen + 1);
126
}
127
#endif
128
129
int
130
rtpp_epoll_wait(int epfd, struct epoll_event *events,
131
  int maxevents, int timeout)
132
5.17k
{
133
#if HAVE_KQUEUE
134
    struct kevent *kep;
135
    struct timespec tot, *top;
136
    int ret, kret;
137
138
    kep = alloca(sizeof(struct kevent) * maxevents);
139
    if (kep == NULL)
140
        return (-1);
141
    if (timeout >= 0) {
142
        tot.tv_sec = timeout / 1000;
143
        tot.tv_nsec = (timeout % 1000) * 1000000;
144
        top = &tot;
145
    } else {
146
        top = NULL;
147
    }
148
    kret = kevent(epfd, NULL, 0, kep, maxevents, top);
149
    if (kret <= 0)
150
        return (kret);
151
    ret = 0;
152
    for (int i = 0; i < kret; i++) {
153
        ret = append_kevent(events, ret, kep, i);
154
    }
155
    return (ret);
156
#else
157
5.17k
    return (epoll_wait(epfd, events, maxevents, timeout));
158
5.17k
#endif
159
5.17k
}