/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 | } |