blob: 9516699884863afbae31a12bfe30f193e8178d73 [file] [log] [blame]
James Kuszmaul871d0712021-01-17 11:30:43 -08001/**
2 * @file rcand.c Remote ICE Candidates
3 *
4 * Copyright (C) 2010 - 2015 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_net.h>
15#include <re_stun.h>
16#include <re_ice.h>
17#include <re_trice.h>
18#include "trice.h"
19
20
21#define DEBUG_MODULE "rcand"
22#define DEBUG_LEVEL 5
23#include <re_dbg.h>
24
25
26static void rcand_destructor(void *data)
27{
28 struct ice_rcand *cand = data;
29
30 list_unlink(&cand->le);
31}
32
33
34static int trice_add_rcandidate(struct ice_rcand **candp,
35 struct list *lst,
36 unsigned compid, const char *foundation,
37 int proto,
38 uint32_t prio, const struct sa *addr,
39 enum ice_cand_type type,
40 enum ice_tcptype tcptype)
41{
42 struct ice_rcand *cand;
43 int err = 0;
44
45 if (!lst || !compid || !foundation || !proto || !addr)
46 return EINVAL;
47
48 cand = mem_zalloc(sizeof(*cand), rcand_destructor);
49 if (!cand)
50 return ENOMEM;
51
52 cand->attr.compid = compid;
53 str_ncpy(cand->attr.foundation, foundation,
54 sizeof(cand->attr.foundation));
55 cand->attr.proto = proto;
56 cand->attr.prio = prio;
57 cand->attr.addr = *addr;
58 cand->attr.type = type;
59 cand->attr.tcptype = tcptype;
60
61 if (err)
62 goto out;
63
64 list_append(lst, &cand->le, cand);
65
66 out:
67 if (err)
68 mem_deref(cand);
69 else if (candp)
70 *candp = cand;
71
72 return err;
73}
74
75
76/* you can call this at any time */
77int trice_rcand_add(struct ice_rcand **rcandp, struct trice *icem,
78 unsigned compid, const char *foundation,
79 int proto, uint32_t prio,
80 const struct sa *addr, enum ice_cand_type type,
81 enum ice_tcptype tcptype)
82{
83 struct ice_rcand *rcand;
84 int sa_flags = SA_ADDR;
85 int err = 0;
86
87 if (!icem || !foundation)
88 return EINVAL;
89
90 if (proto == IPPROTO_UDP)
91 sa_flags |= SA_PORT;
92
93 if (proto == IPPROTO_TCP &&
94 (tcptype == ICE_TCP_PASSIVE || tcptype == ICE_TCP_SO))
95 sa_flags |= SA_PORT;
96
97 if (!sa_isset(addr, sa_flags)) {
98 DEBUG_WARNING("add_remote_candidate: invalid address"
99 " (%J) for %s.%s\n",
100 addr, net_proto2name(proto),
101 ice_tcptype_name(tcptype));
102 return EINVAL;
103 }
104
105 /* avoid duplicates */
106 rcand = trice_rcand_find(icem, compid, proto, addr);
107 if (rcand) {
108
109 if (rcand->attr.type == ICE_CAND_TYPE_PRFLX &&
110 prio > rcand->attr.prio) {
111
112 rcand->attr.type = type;
113 rcand->attr.prio = prio;
114 }
115
116 goto out;
117 }
118
119 err = trice_add_rcandidate(&rcand, &icem->rcandl,
120 compid, foundation,
121 proto, prio, addr, type, tcptype);
122 if (err)
123 goto out;
124
125 if (icem->lrole != ICE_ROLE_UNKNOWN) {
126 /* pair this remote-candidate with all existing
127 * local-candidates */
128 err = trice_candpair_with_remote(icem, rcand);
129 if (err)
130 goto out;
131
132 /* new pair -- refresh the checklist timer */
133 trice_checklist_refresh(icem);
134 }
135
136 out:
137 if (err)
138 mem_deref(rcand);
139 else if (rcandp)
140 *rcandp = rcand;
141
142 return err;
143}
144
145
146struct ice_rcand *trice_rcand_find(struct trice *icem,
147 unsigned compid, int proto,
148 const struct sa *addr)
149{
150 struct list *lst;
151 struct le *le;
152
153 if (!icem)
154 return NULL;
155
156 if (!proto) {
157 DEBUG_WARNING("find_candidate: invalid args\n");
158 return NULL;
159 }
160
161 lst = &icem->rcandl;
162
163 for (le = list_head(lst); le; le = le->next) {
164
165 struct ice_cand_attr *cand = le->data;
166
167 if (compid && cand->compid != compid)
168 continue;
169
170 if (cand->proto != proto)
171 continue;
172
173 if (addr && !sa_cmp(&cand->addr, addr, SA_ALL))
174 continue;
175
176 return (void *)cand;
177 }
178
179 return NULL;
180}
181
182
183int trice_rcands_debug(struct re_printf *pf, const struct list *lst)
184{
185 struct le *le;
186 int err;
187
188 err = re_hprintf(pf, " (%u)\n", list_count(lst));
189
190 for (le = list_head(lst); le && !err; le = le->next) {
191
192 const struct ice_rcand *rcand = le->data;
193
194 err |= re_hprintf(pf, " {%u} "
195 "fnd=%-8s prio=%08x %24H",
196 rcand->attr.compid,
197 rcand->attr.foundation,
198 rcand->attr.prio,
199 trice_cand_print, rcand);
200
201 err |= re_hprintf(pf, "\n");
202 }
203
204 return err;
205}