Coverage Report

Created: 2025-07-18 07:10

/src/rtpproxy/src/rtpp_weakref.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3
 * Copyright (c) 2006-2015 Sippy Software, Inc., http://www.sippysoft.com
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 */
28
29
#include <pthread.h>
30
#include <stddef.h>
31
#include <stdint.h>
32
#include <stdlib.h>
33
34
#include "rtpp_types.h"
35
#include "rtpp_hash_table.h"
36
#include "rtpp_codeptr.h"
37
#include "rtpp_refcnt.h"
38
#include "rtpp_weakref.h"
39
#include "rtpp_weakref_fin.h"
40
#include "rtpp_mallocs.h"
41
42
DEFINE_CB_STRUCT(rtpp_weakref);
43
44
struct rtpp_weakref_priv {
45
    struct rtpp_weakref pub;
46
    rtpp_weakref_cb_s on_first;
47
    rtpp_weakref_cb_s on_last;
48
    pthread_mutex_t on_lock;
49
};
50
51
static void rtpp_weakref_dtor(struct rtpp_weakref_priv *);
52
static int rtpp_weakref_reg(struct rtpp_weakref *, struct rtpp_refcnt *, uint64_t);
53
static void *rtpp_wref_get_by_idx(struct rtpp_weakref *, uint64_t);
54
static struct rtpp_refcnt *rtpp_weakref_unreg(struct rtpp_weakref *, uint64_t);
55
static struct rtpp_refcnt *rtpp_weakref_move(struct rtpp_weakref *, uint64_t,
56
  struct rtpp_weakref *);
57
static void rtpp_wref_foreach(struct rtpp_weakref *, rtpp_weakref_foreach_t,
58
  void *);
59
static int rtpp_wref_get_length(struct rtpp_weakref *);
60
static int rtpp_wref_purge(struct rtpp_weakref *);
61
static rtpp_weakref_cb_t rtpp_wref_set_on_first(struct rtpp_weakref *, rtpp_weakref_cb_t,
62
  void *);
63
static rtpp_weakref_cb_t rtpp_wref_set_on_last(struct rtpp_weakref *, rtpp_weakref_cb_t,
64
  void *);
65
66
DEFINE_SMETHODS(rtpp_weakref,
67
    .reg = &rtpp_weakref_reg,
68
    .get_by_idx = &rtpp_wref_get_by_idx,
69
    .unreg = &rtpp_weakref_unreg,
70
    .move = &rtpp_weakref_move,
71
    .foreach = &rtpp_wref_foreach,
72
    .get_length = &rtpp_wref_get_length,
73
    .purge = &rtpp_wref_purge,
74
    .set_on_first = &rtpp_wref_set_on_first,
75
    .set_on_last = &rtpp_wref_set_on_last,
76
);
77
78
struct rtpp_weakref *
79
rtpp_weakref_ctor(void)
80
10
{
81
10
    struct rtpp_weakref_priv *pvt;
82
83
10
    pvt = rtpp_rzmalloc(sizeof(struct rtpp_weakref_priv), PVT_RCOFFS(pvt));
84
10
    if (pvt == NULL) {
85
0
        return (NULL);
86
0
    }
87
10
    pvt->pub.ht = rtpp_hash_table_ctor(rtpp_ht_key_u64_t, RTPP_HT_NODUPS |
88
10
      RTPP_HT_DUP_ABRT);
89
10
    if (pvt->pub.ht == NULL) {
90
0
        goto e0;
91
0
    }
92
10
    if (pthread_mutex_init(&pvt->on_lock, NULL) != 0) {
93
0
        goto e1;
94
0
    }
95
10
    PUBINST_FININIT(&pvt->pub, pvt, rtpp_weakref_dtor);
96
10
    return (&pvt->pub);
97
0
e1:
98
0
    RTPP_OBJ_DECREF(pvt->pub.ht);
99
0
e0:
100
0
    RTPP_OBJ_DECREF(&(pvt->pub));
101
0
    return (NULL);
102
0
}
103
104
static int
105
rtpp_weakref_reg(struct rtpp_weakref *pub, struct rtpp_refcnt *sp,
106
  uint64_t suid)
107
113k
{
108
113k
    struct rtpp_weakref_priv *pvt;
109
113k
    struct rtpp_ht_opstats hos, *hosp;
110
113k
    int rval;
111
112
113k
    PUB2PVT(pub, pvt);
113
114
113k
    if (pvt->on_first.func != NULL) {
115
0
        pthread_mutex_lock(&pvt->on_lock);
116
0
        hos.first = 0;
117
0
        hosp = &hos;
118
113k
    } else {
119
113k
        hosp = NULL;
120
113k
    }
121
122
113k
    rval = 0;
123
113k
    if (CALL_SMETHOD(pvt->pub.ht, append_refcnt, &suid, sp, hosp) == NULL) {
124
0
        rval = -1;
125
0
    }
126
113k
    if (pvt->on_first.func != NULL) {
127
0
        if (rval == 0 && hosp->first)
128
0
            pvt->on_first.func(pvt->on_first.arg);
129
0
        pthread_mutex_unlock(&pvt->on_lock);
130
0
    }
131
113k
    return (rval);
132
113k
}
133
134
static struct rtpp_refcnt *
135
rtpp_weakref_unreg(struct rtpp_weakref *pub, uint64_t suid)
136
90.8k
{
137
90.8k
    struct rtpp_weakref_priv *pvt;
138
90.8k
    struct rtpp_refcnt *sp;
139
90.8k
    struct rtpp_ht_opstats hos, *hosp;
140
141
90.8k
    PUB2PVT(pub, pvt);
142
143
90.8k
    if (pvt->on_last.func != NULL) {
144
0
        pthread_mutex_lock(&pvt->on_lock);
145
0
        hos.last = 0;
146
0
        hosp = &hos;
147
90.8k
    } else {
148
90.8k
        hosp = NULL;
149
90.8k
    }
150
151
90.8k
    sp = CALL_SMETHOD(pvt->pub.ht, remove_by_key, &suid, hosp);
152
153
90.8k
    if (pvt->on_last.func != NULL) {
154
0
        if (sp != NULL && hosp->last)
155
0
            pvt->on_last.func(pvt->on_last.arg);
156
0
        pthread_mutex_unlock(&pvt->on_lock);
157
0
    }
158
159
90.8k
    return (sp);
160
90.8k
}
161
162
static struct rtpp_refcnt *
163
rtpp_weakref_move(struct rtpp_weakref *pub, uint64_t suid,
164
  struct rtpp_weakref *other)
165
0
{
166
0
    struct rtpp_weakref_priv *pvt, *pvt_other;
167
168
0
    struct rtpp_refcnt *sp;
169
0
    struct rtpp_ht_opstats hos = {}, *hosp = NULL;
170
171
0
    PUB2PVT(pub, pvt);
172
0
    PUB2PVT(other, pvt_other);
173
174
0
    if (pvt->on_last.func != NULL) {
175
0
        pthread_mutex_lock(&pvt->on_lock);
176
0
        hosp = &hos;
177
0
    }
178
0
    if (pvt_other->on_first.func != NULL) {
179
0
        pthread_mutex_lock(&pvt_other->on_lock);
180
0
        hosp = &hos;
181
0
    }
182
183
0
    sp = CALL_SMETHOD(pvt->pub.ht, transfer, &suid, pvt_other->pub.ht, hosp);
184
185
0
    if (pvt->on_last.func != NULL) {
186
0
        if (sp != NULL && hosp->last)
187
0
            pvt->on_last.func(pvt->on_last.arg);
188
0
        pthread_mutex_unlock(&pvt->on_lock);
189
0
    }
190
0
    if (pvt_other->on_first.func != NULL) {
191
0
        if (sp != NULL && hosp->first)
192
0
            pvt_other->on_first.func(pvt_other->on_first.arg);
193
0
        pthread_mutex_unlock(&pvt_other->on_lock);
194
0
    }
195
196
0
    return (sp);
197
0
}
198
199
static void
200
rtpp_weakref_dtor(struct rtpp_weakref_priv *pvt)
201
10
{
202
203
10
    rtpp_weakref_fin(&(pvt->pub));
204
10
    pthread_mutex_destroy(&pvt->on_lock);
205
10
    RTPP_OBJ_DECREF(pvt->pub.ht);
206
10
}
207
208
static void *
209
rtpp_wref_get_by_idx(struct rtpp_weakref *pub, uint64_t suid)
210
8.82k
{
211
8.82k
    struct rtpp_weakref_priv *pvt;
212
8.82k
    struct rtpp_refcnt *rco;
213
214
8.82k
    PUB2PVT(pub, pvt);
215
216
8.82k
    rco = CALL_SMETHOD(pvt->pub.ht, find, &suid);
217
8.82k
    if (rco == NULL) {
218
0
        return (NULL);
219
0
    }
220
8.82k
    return (CALL_SMETHOD(rco, getdata));
221
8.82k
}
222
223
static void
224
rtpp_wref_foreach(struct rtpp_weakref *pub, rtpp_weakref_foreach_t foreach_f,
225
  void *foreach_d)
226
0
{
227
0
    struct rtpp_weakref_priv *pvt;
228
0
    struct rtpp_ht_opstats hos, *hosp;
229
230
0
    PUB2PVT(pub, pvt);
231
232
0
    if (pvt->on_last.func != NULL) {
233
0
        pthread_mutex_lock(&pvt->on_lock);
234
0
        hos.last = 0;
235
0
        hosp = &hos;
236
0
    } else {
237
0
        hosp = NULL;
238
0
    }
239
240
0
    CALL_SMETHOD(pvt->pub.ht, foreach, foreach_f, foreach_d, hosp);
241
242
0
    if (pvt->on_last.func != NULL) {
243
0
        if (hosp->last)
244
0
            pvt->on_last.func(pvt->on_last.arg);
245
0
        pthread_mutex_unlock(&pvt->on_lock);
246
0
    }
247
0
}
248
249
static int
250
rtpp_wref_get_length(struct rtpp_weakref *pub)
251
22.7k
{
252
22.7k
    struct rtpp_weakref_priv *pvt;
253
254
22.7k
    PUB2PVT(pub, pvt);
255
22.7k
    return (CALL_SMETHOD(pvt->pub.ht, get_length));
256
22.7k
}
257
258
static int
259
rtpp_wref_purge(struct rtpp_weakref *pub)
260
4.54k
{
261
4.54k
    struct rtpp_weakref_priv *pvt;
262
4.54k
    int npurged;
263
264
4.54k
    PUB2PVT(pub, pvt);
265
266
4.54k
    if (pvt->on_last.func != NULL) {
267
0
        pthread_mutex_lock(&pvt->on_lock);
268
0
    }
269
270
4.54k
    npurged = CALL_SMETHOD(pvt->pub.ht, purge);
271
272
4.54k
    if (pvt->on_last.func != NULL) {
273
0
        if (npurged > 0)
274
0
            pvt->on_last.func(pvt->on_last.arg);
275
0
        pthread_mutex_unlock(&pvt->on_lock);
276
0
    }
277
4.54k
    return (npurged);
278
4.54k
}
279
280
static rtpp_weakref_cb_t
281
rtpp_wref_set_on_first(struct rtpp_weakref *pub, rtpp_weakref_cb_t cb_func,
282
  void *cb_func_arg)
283
0
{
284
0
    struct rtpp_weakref_priv *pvt;
285
0
    rtpp_weakref_cb_t prev;
286
287
0
    PUB2PVT(pub, pvt);
288
0
    prev = pvt->on_first.func;
289
0
    pvt->on_first.func = cb_func;
290
0
    pvt->on_first.arg = cb_func_arg;
291
0
    return (prev);
292
0
}
293
294
static rtpp_weakref_cb_t
295
rtpp_wref_set_on_last(struct rtpp_weakref *pub, rtpp_weakref_cb_t cb_func,
296
  void *cb_func_arg)
297
0
{
298
0
    struct rtpp_weakref_priv *pvt;
299
0
    rtpp_weakref_cb_t prev;
300
301
0
    PUB2PVT(pub, pvt);
302
0
    prev = pvt->on_last.func;
303
0
    pvt->on_last.func = cb_func;
304
0
    pvt->on_last.arg = cb_func_arg;
305
0
    return (prev);
306
0
}