Coverage Report

Created: 2026-03-14 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rtpproxy/external/libre/src/ice/cand.c
Line
Count
Source
1
/**
2
 * @file cand.c  ICE Candidates
3
 *
4
 * Copyright (C) 2010 Creytiv.com
5
 */
6
#include <string.h>
7
#include <re_types.h>
8
#include <re_fmt.h>
9
#include <re_mem.h>
10
#include <re_mbuf.h>
11
#include <re_list.h>
12
#include <re_tmr.h>
13
#include <re_sa.h>
14
#include <re_sys.h>
15
#include <re_stun.h>
16
#include <re_turn.h>
17
#include <re_ice.h>
18
#include "ice.h"
19
20
21
#define DEBUG_MODULE "icecand"
22
#define DEBUG_LEVEL 5
23
#include <re_dbg.h>
24
25
26
static void cand_destructor(void *arg)
27
28.9k
{
28
28.9k
  struct ice_cand *cand = arg;
29
30
28.9k
  list_unlink(&cand->le);
31
28.9k
  mem_deref(cand->foundation);
32
28.9k
  mem_deref(cand->ifname);
33
34
28.9k
  if (cand != cand->base)
35
21.1k
    mem_deref(cand->base);
36
28.9k
}
37
38
39
/** Foundation is a hash of IP address and candidate type */
40
static int compute_foundation(struct ice_cand *cand)
41
7.75k
{
42
7.75k
  uint32_t v;
43
44
7.75k
  v  = sa_hash(&cand->addr, SA_ADDR);
45
7.75k
  v ^= cand->type;
46
47
7.75k
  return re_sdprintf(&cand->foundation, "%08x", v);
48
7.75k
}
49
50
51
static int cand_alloc(struct ice_cand **candp, struct icem *icem,
52
          enum ice_cand_type type, unsigned compid,
53
          uint32_t prio, const char *ifname,
54
          enum ice_transp transp, const struct sa *addr)
55
7.75k
{
56
7.75k
  struct ice_cand *cand;
57
7.75k
  int err;
58
59
7.75k
  if (!icem)
60
0
    return EINVAL;
61
62
7.75k
  cand = mem_zalloc(sizeof(*cand), cand_destructor);
63
7.75k
  if (!cand)
64
0
    return ENOMEM;
65
66
7.75k
  list_append(&icem->lcandl, &cand->le, cand);
67
68
7.75k
  cand->type   = type;
69
7.75k
  cand->compid = compid;
70
7.75k
  cand->prio   = prio;
71
7.75k
  cand->transp = transp;
72
73
7.75k
  sa_cpy(&cand->addr, addr);
74
75
7.75k
  err = compute_foundation(cand);
76
77
7.75k
  if (ifname)
78
0
    err |= str_dup(&cand->ifname, ifname);
79
80
7.75k
  if (err)
81
0
    mem_deref(cand);
82
7.75k
  else if (candp)
83
7.75k
    *candp = cand;
84
85
7.75k
  return err;
86
7.75k
}
87
88
89
int icem_lcand_add_base(struct icem *icem, unsigned compid, uint16_t lprio,
90
      const char *ifname, enum ice_transp transp,
91
      const struct sa *addr)
92
7.75k
{
93
7.75k
  struct icem_comp *comp;
94
7.75k
  struct ice_cand *cand;
95
7.75k
  int err;
96
97
7.75k
  comp = icem_comp_find(icem, compid);
98
7.75k
  if (!comp)
99
0
    return ENOENT;
100
101
7.75k
  err = cand_alloc(&cand, icem, ICE_CAND_TYPE_HOST, compid,
102
7.75k
       ice_cand_calc_prio(ICE_CAND_TYPE_HOST, lprio, compid),
103
7.75k
       ifname, transp, addr);
104
7.75k
  if (err)
105
0
    return err;
106
107
  /* the base is itself */
108
7.75k
  cand->base = cand;
109
110
7.75k
  sa_set_port(&cand->addr, comp->lport);
111
112
7.75k
  return 0;
113
7.75k
}
114
115
116
int icem_lcand_add(struct icem *icem, struct ice_cand *base,
117
       enum ice_cand_type type,
118
       const struct sa *addr)
119
0
{
120
0
  struct ice_cand *cand;
121
0
  int err;
122
123
0
  if (!base)
124
0
    return EINVAL;
125
126
0
  err = cand_alloc(&cand, icem, type, base->compid,
127
0
       ice_cand_calc_prio(type, 0, base->compid),
128
0
       base->ifname, base->transp, addr);
129
0
  if (err)
130
0
    return err;
131
132
0
  cand->base = mem_ref(base);
133
0
  sa_cpy(&cand->rel, &base->addr);
134
135
0
  return 0;
136
0
}
137
138
139
int icem_rcand_add(struct icem *icem, enum ice_cand_type type, unsigned compid,
140
       uint32_t prio, const struct sa *addr,
141
       const struct sa *rel_addr, const struct pl *foundation)
142
21.1k
{
143
21.1k
  struct ice_cand *rcand;
144
21.1k
  int err;
145
146
21.1k
  if (!icem || !foundation)
147
0
    return EINVAL;
148
149
21.1k
  rcand = mem_zalloc(sizeof(*rcand), cand_destructor);
150
21.1k
  if (!rcand)
151
0
    return ENOMEM;
152
153
21.1k
  list_append(&icem->rcandl, &rcand->le, rcand);
154
155
21.1k
  rcand->type   = type;
156
21.1k
  rcand->compid = compid;
157
21.1k
  rcand->prio   = prio;
158
159
21.1k
  sa_cpy(&rcand->addr, addr);
160
21.1k
  sa_cpy(&rcand->rel, rel_addr);
161
162
21.1k
  err = pl_strdup(&rcand->foundation, foundation);
163
164
21.1k
  if (err)
165
0
    mem_deref(rcand);
166
167
21.1k
  return err;
168
21.1k
}
169
170
171
int icem_rcand_add_prflx(struct ice_cand **rcp, struct icem *icem,
172
       unsigned compid, uint32_t prio,
173
       const struct sa *addr)
174
0
{
175
0
  struct ice_cand *rcand;
176
0
  int err;
177
178
0
  if (!icem || !addr)
179
0
    return EINVAL;
180
181
0
  rcand = mem_zalloc(sizeof(*rcand), cand_destructor);
182
0
  if (!rcand)
183
0
    return ENOMEM;
184
185
0
  list_append(&icem->rcandl, &rcand->le, rcand);
186
187
0
  rcand->type   = ICE_CAND_TYPE_PRFLX;
188
0
  rcand->compid = compid;
189
0
  rcand->prio   = prio;
190
0
  rcand->addr   = *addr;
191
192
0
  err = re_sdprintf(&rcand->foundation, "%08x", rand_u32());
193
0
  if (err)
194
0
    goto out;
195
196
0
  icecomp_printf(icem_comp_find(icem, compid),
197
0
           "added PeerReflexive remote candidate"
198
0
           " with priority %u (%J)\n", prio, addr);
199
200
0
 out:
201
0
  if (err)
202
0
    mem_deref(rcand);
203
0
  else if (rcp)
204
0
    *rcp = rcand;
205
206
0
  return err;
207
0
}
208
209
210
struct ice_cand *icem_cand_find(const struct list *lst, unsigned compid,
211
        const struct sa *addr)
212
22.4k
{
213
22.4k
  struct le *le;
214
215
60.1k
  for (le = list_head(lst); le; le = le->next) {
216
217
39.0k
    struct ice_cand *cand = le->data;
218
219
39.0k
    if (compid && cand->compid != compid)
220
4.45k
      continue;
221
222
34.5k
    if (addr && !sa_cmp(&cand->addr, addr, SA_ALL))
223
33.2k
      continue;
224
225
1.30k
    return cand;
226
34.5k
  }
227
228
21.1k
  return NULL;
229
22.4k
}
230
231
232
/**
233
 * Find the highest priority LCAND on the check-list of type HOST/RELAY
234
 *
235
 * @param icem    ICE Media object
236
 * @param compid  Component ID
237
 *
238
 * @return Local candidate if found, otherwise NULL
239
 */
240
struct ice_cand *icem_lcand_find_checklist(const struct icem *icem,
241
             unsigned compid)
242
0
{
243
0
  struct le *le;
244
245
0
  for (le = icem->checkl.head; le; le = le->next) {
246
0
    struct ice_candpair *cp = le->data;
247
248
0
    if (cp->lcand->compid != compid)
249
0
      continue;
250
251
0
    switch (cp->lcand->type) {
252
253
0
    case ICE_CAND_TYPE_HOST:
254
0
    case ICE_CAND_TYPE_RELAY:
255
0
      return cp->lcand;
256
257
0
    default:
258
0
      break;
259
0
    }
260
0
  }
261
262
0
  return NULL;
263
0
}
264
265
266
struct ice_cand *icem_lcand_base(struct ice_cand *lcand)
267
0
{
268
0
  return lcand ? lcand->base : NULL;
269
0
}
270
271
272
const struct sa *icem_lcand_addr(const struct ice_cand *cand)
273
0
{
274
0
  return cand ? &cand->addr : NULL;
275
0
}
276
277
278
int icem_cands_debug(struct re_printf *pf, const struct list *lst)
279
0
{
280
0
  struct le *le;
281
0
  int err;
282
283
0
  err = re_hprintf(pf, " (%u)\n", list_count(lst));
284
285
0
  for (le = list_head(lst); le && !err; le = le->next) {
286
287
0
    const struct ice_cand *cand = le->data;
288
289
0
    err |= re_hprintf(pf, "  {%u} fnd=%-2s prio=%08x %24H",
290
0
          cand->compid, cand->foundation, cand->prio,
291
0
          icem_cand_print, cand);
292
293
0
    if (sa_isset(&cand->rel, SA_ADDR))
294
0
      err |= re_hprintf(pf, " (rel-addr=%J)", &cand->rel);
295
296
0
    err |= re_hprintf(pf, "\n");
297
0
  }
298
299
0
  return err;
300
0
}
301
302
303
int icem_cand_print(struct re_printf *pf, const struct ice_cand *cand)
304
0
{
305
0
  int err = 0;
306
307
0
  if (!cand)
308
0
    return 0;
309
310
0
  if (cand->ifname)
311
0
    err |= re_hprintf(pf, "%s:", cand->ifname);
312
313
0
  err |= re_hprintf(pf, "%s:%J",
314
0
        ice_cand_type2name(cand->type), &cand->addr);
315
316
0
  return err;
317
0
}
318
319
enum ice_cand_type icem_cand_type(const struct ice_cand *cand)
320
0
{
321
0
  return cand ? cand->type : (enum ice_cand_type)-1;
322
0
}