Bug Summary

File:root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate_pair.cpp
Warning:line 714, column 9
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ice_candidate_pair.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/webrtc/transport/third_party/nICEr/nicer_nicer -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/webrtc/transport/third_party/nICEr/nicer_nicer -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D _FILE_OFFSET_BITS=64 -D CHROMIUM_BUILD -D USE_LIBJPEG_TURBO=1 -D USE_NSS=1 -D ENABLE_ONE_CLICK_SIGNIN -D GTK_DISABLE_SINGLE_INCLUDES=1 -D _ISOC99_SOURCE=1 -D ENABLE_REMOTING=1 -D ENABLE_WEBRTC=1 -D ENABLE_CONFIGURATION_POLICY -D ENABLE_INPUT_SPEECH -D ENABLE_NOTIFICATIONS -D ENABLE_GPU=1 -D ENABLE_EGLIMAGE=1 -D USE_SKIA=1 -D ENABLE_TASK_MANAGER=1 -D ENABLE_WEB_INTENTS=1 -D ENABLE_EXTENSIONS=1 -D ENABLE_PLUGIN_INSTALLATION=1 -D ENABLE_PROTECTOR_SERVICE=1 -D ENABLE_SESSION_SERVICE=1 -D ENABLE_THEMES=1 -D ENABLE_BACKGROUND=1 -D ENABLE_AUTOMATION=1 -D ENABLE_PRINTING=1 -D ENABLE_CAPTIVE_PORTAL_DETECTION=1 -D SANITY_CHECKS -D USE_TURN -D USE_ICE -D USE_RFC_3489_BACKWARDS_COMPATIBLE -D USE_STUN_PEDANTIC -D NR_SOCKET_IS_VOID_PTR -D restrict= -D R_PLATFORM_INT_TYPES=<stdint.h> -D R_DEFINED_INT2=int16_t -D R_DEFINED_UINT2=uint16_t -D R_DEFINED_INT4=int32_t -D R_DEFINED_UINT4=uint32_t -D R_DEFINED_INT8=int64_t -D R_DEFINED_UINT8=uint64_t -D LINUX -D HAVE_LIBM=1 -D HAVE_STRDUP=1 -D HAVE_STRLCPY=1 -D HAVE_SYS_TIME_H=1 -D HAVE_VFPRINTF=1 -D NEW_STDIORETSIGTYPE=void -D TIME_WITH_SYS_TIME_H=1 -D __UNUSED__=__attribute__((unused)) -D DYNAMIC_ANNOTATIONS_ENABLED=1 -D WTF_USE_DYNAMIC_ANNOTATIONS=1 -D _DEBUG -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/webrtc/transport/third_party/nICEr/nicer_nicer -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/event -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/log -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/registry -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/share -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/util -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/port/generic/include -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/crypto -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/net -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/util -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/port/linux/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -Wno-parentheses -Wno-format -Wno-format-security -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c++ /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate_pair.cpp
1/*
2Copyright (c) 2007, Adobe Systems, Incorporated
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9* Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12* Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16* Neither the name of Adobe Systems, Network Resonance nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*/
32
33#include <assert.h>
34#include <string.h>
35#include <nr_api.h>
36#include "async_timer.h"
37#include "ice_ctx.h"
38#include "ice_util.h"
39#include "ice_codeword.h"
40#include "stun.h"
41
42static const char *nr_ice_cand_pair_states[]={"UNKNOWN","FROZEN","WAITING","IN_PROGRESS","FAILED","SUCCEEDED","CANCELLED"};
43
44static void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg);
45static void nr_ice_candidate_pair_restart_stun_role_change_cb(NR_SOCKET s, int how, void *cb_arg);
46static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
47 nr_ice_candidate *lcand, nr_ice_candidate *rcand);
48
49static void nr_ice_candidate_pair_set_priority(nr_ice_cand_pair *pair)
50 {
51 /* Priority computation S 5.7.2 */
52 UINT8 controlling_priority, controlled_priority;
53 if(pair->pctx->controlling)
54 {
55 controlling_priority=pair->local->priority;
56 controlled_priority=pair->remote->priority;
57 }
58 else{
59 controlling_priority=pair->remote->priority;
60 controlled_priority=pair->local->priority;
61 }
62 pair->priority=(MIN(controlling_priority, controlled_priority)(((controlling_priority)<(controlled_priority))?(controlling_priority
):(controlled_priority))
)<<32 |
63 (MAX(controlling_priority, controlled_priority)(((controlling_priority)>(controlled_priority))?(controlling_priority
):(controlled_priority))
)<<1 |
64 (controlled_priority > controlling_priority?0:1);
65 }
66
67int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp)
68 {
69 nr_ice_cand_pair *pair=0;
70 int r,_status;
71 UINT4 RTO;
72 nr_ice_candidate tmpcand;
73 UINT8 t_priority;
74 int flags = 0;
75
76 if(!(pair=R_NEW(nr_ice_cand_pair)(nr_ice_cand_pair*)calloc(1,sizeof(nr_ice_cand_pair))))
77 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
78
79 pair->pctx=pctx;
80
81 nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand);
82
83 if(r=nr_concat_strings(&pair->as_string,pair->codeword,"|",lcand->addr.as_string,"|",
84 rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")", NULL__null))
85 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
86
87 nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN1);
88 pair->local=lcand;
89 pair->remote=rcand;
90
91 nr_ice_candidate_pair_set_priority(pair);
92
93 /*
94 TODO(bcampen@mozilla.com): Would be nice to log why this candidate was
95 created (initial pair generation, triggered check, and new trickle
96 candidate seem to be the possibilities here).
97 */
98 r_log(LOG_ICE,LOG_INFO6,"ICE(%s)/CAND-PAIR(%s): Pairing candidate %s (%x):%s (%x) priority=%llu (%llx)",pctx->ctx->label,pair->codeword,lcand->addr.as_string,lcand->priority,rcand->addr.as_string,rcand->priority,pair->priority,pair->priority);
99
100 /* Foundation */
101 if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|",
102 rcand->foundation,NULL__null))
103 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
104
105 /* Compute the RTO per S 16 */
106 RTO = MAX(100, (pctx->ctx->Ta * pctx->waiting_pairs))(((100)>((pctx->ctx->Ta * pctx->waiting_pairs)))?
(100):((pctx->ctx->Ta * pctx->waiting_pairs)))
;
107
108 /* Make a bogus candidate to compute a theoretical peer reflexive
109 * priority per S 7.1.1.1 */
110 memcpy(&tmpcand, lcand, sizeof(tmpcand));
111 /* Non-standard behavior, but that's because the standard is wrong! If
112 * this is a relay candidate, it is never appropriate to assign it the
113 * priority of a prflx. One could attempt to compensate for this on the
114 * other side by overriding prflx candidates (and their priority) when
115 * identical trickle candidates arrive, but it is prudent to avoid creating
116 * this situation in the first place.
117 * TODO: It may be appropriate to assign it a higher priority than _other_
118 * relay candidates. However, there are probably very few cases where it
119 * would matter.
120 * TODO: Note that we still have to contend with mismatched priorities for
121 * srflx here; if we have two srflx, and one of them is learned by the
122 * other side as a prflx, the other side is going to have a higher priority
123 * for that pair unless the priority is updated. For ICE-bis nomination,
124 * this won't matter a whole lot, but we do aggressive nomination, and
125 * there it is crucial. The controlled side has to pick the highest
126 * priority nominated pair, and all of them will get nominated. */
127 if (tmpcand.type != RELAYED) {
128 tmpcand.type = PEER_REFLEXIVE;
129 }
130 if (r=nr_ice_candidate_compute_priority(&tmpcand))
131 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
132 t_priority = tmpcand.priority;
133
134 flags = NR_STUN_TRANSPORT_ADDR_CHECK_WILDCARD1;
135 if (!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ALLOW_LOOPBACK(1 << 7))) {
136 flags |= NR_STUN_TRANSPORT_ADDR_CHECK_LOOPBACK2;
137 }
138 if (!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ALLOW_LINK_LOCAL(1 << 8))) {
139 flags |= NR_STUN_TRANSPORT_ADDR_CHECK_LINK_LOCAL4;
140 }
141
142 /* Our sending context */
143 if (r = nr_stun_client_ctx_create(pair->as_string, lcand->osock,
144 &rcand->addr, RTO, flags,
145 &pair->stun_client))
146 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
147 if(!(pair->stun_client->params.ice_binding_request.username=strdup(rcand->stream->l2r_user)))
148 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
149 if(r=r_data_copy(&pair->stun_client->params.ice_binding_request.password,
150 &rcand->stream->l2r_pass))
151 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
152 /* TODO(ekr@rtfm.com): Do we need to frob this when we change role. Bug 890667 */
153 pair->stun_client->params.ice_binding_request.control = pctx->controlling?
154 NR_ICE_CONTROLLING1:NR_ICE_CONTROLLED2;
155 pair->stun_client->params.ice_binding_request.priority=t_priority;
156
157 pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker;
158
159 *pairp=pair;
160
161 _status=0;
162 abort:
163 if(_status){
164 nr_ice_candidate_pair_destroy(&pair);
165 }
166 return(_status);
167 }
168
169int nr_ice_candidate_pair_destroy(nr_ice_cand_pair **pairp)
170 {
171 nr_ice_cand_pair *pair;
172
173 if(!pairp || !*pairp)
174 return(0);
175
176 pair=*pairp;
177 *pairp=0;
178
179 // record stats back to the ice ctx on destruction
180 if (pair->stun_client) {
181 nr_accumulate_count(&(pair->local->ctx->stats.stun_retransmits), pair->stun_client->retransmit_ct);
182 }
183
184 free(pair->as_string);
185 free(pair->foundation);
186 nr_ice_socket_deregister(pair->local->isock,pair->stun_client_handle);
187 if (pair->stun_client) {
188 free(pair->stun_client->params.ice_binding_request.username);
189 free(pair->stun_client->params.ice_binding_request.password.data);
190 nr_stun_client_ctx_destroy(&pair->stun_client);
191 }
192
193 NR_async_timer_cancel(pair->stun_cb_timer);
194 NR_async_timer_cancel(pair->restart_role_change_cb_timer);
195 NR_async_timer_cancel(pair->restart_nominated_cb_timer);
196
197 free(pair);
198 return(0);
199 }
200
201int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
202 {
203 assert(pair->state==NR_ICE_PAIR_STATE_FROZEN)(static_cast <bool> (pair->state==1) ? void (0) : __assert_fail
("pair->state==NR_ICE_PAIR_STATE_FROZEN", __builtin_FILE (
), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__))
;
204
205 nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING2);
206
207 return(0);
208 }
209
210static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
211 {
212 int r,_status;
213 nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg;
214 int use_candidate=pair->stun_client->mode==NR_ICE_CLIENT_MODE_USE_CANDIDATE10;
215 nr_ice_cand_pair *actual_pair=0;
216 nr_ice_candidate *cand=0;
217 nr_stun_message *sres;
218 nr_transport_addr *request_src;
219 nr_transport_addr *request_dst;
220 nr_transport_addr *response_src;
221 nr_transport_addr response_dst;
222 nr_stun_message_attribute *attr;
223
224 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s): STUN cb on pair addr = %s",
225 pair->pctx->label,pair->local->stream->label,pair->codeword,pair->as_string);
226
227 /* This ordinarily shouldn't happen, but can if we're
228 doing the second check to confirm nomination.
229 Just bail out */
230 if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED5)
231 goto done;
232
233 switch(pair->stun_client->state){
234 case NR_STUN_CLIENT_STATE_FAILED3:
235 sres=pair->stun_client->response;
236 if(sres && nr_stun_message_has_attribute(sres,NR_STUN_ATTR_ERROR_CODE0x0009,&attr)&&attr->u.error_code.number==487){
237
238 /*
239 * Flip the controlling bit; subsequent 487s for other pairs will be
240 * ignored, since we abandon their STUN transactions.
241 */
242 nr_ice_peer_ctx_switch_controlling_role(pair->pctx);
243
244 return;
245 }
246 [[fallthrough]];
247 case NR_STUN_CLIENT_STATE_TIMED_OUT4:
248 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
249 break;
250 case NR_STUN_CLIENT_STATE_DONE2:
251 /* make sure the addresses match up S 7.1.2.2 */
252 response_src=&pair->stun_client->peer_addr;
253 request_dst=&pair->remote->addr;
254 if (nr_transport_addr_cmp(response_src,request_dst,NR_TRANSPORT_ADDR_CMP_MODE_ALL4)){
255 r_log(LOG_ICE,LOG_WARNING4,"ICE-PEER(%s)/CAND-PAIR(%s): Peer address mismatch %s != %s",pair->pctx->label,pair->codeword,response_src->as_string,request_dst->as_string);
256 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
257 break;
258 }
259 request_src=&pair->stun_client->my_addr;
260 nr_socket_getaddr(pair->local->osock,&response_dst);
261 if (nr_transport_addr_cmp(request_src,&response_dst,NR_TRANSPORT_ADDR_CMP_MODE_ALL4)){
262 r_log(LOG_ICE,LOG_WARNING4,"ICE-PEER(%s)/CAND-PAIR(%s): Local address mismatch %s != %s",pair->pctx->label,pair->codeword,request_src->as_string,response_dst.as_string);
263 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
264 break;
265 }
266
267 // Update the rtt related fields
268 if (pair->stun_client->rtt_valid) {
269 nr_ice_candidate_pair_update_rtt(pair, pair->stun_client->rtt_ms);
270 // clear rtt_ms so we can't double process it.
271 pair->stun_client->rtt_valid = 0;
272 pair->stun_client->rtt_ms = 0;
273 }
274
275 if (pair->local->type == RELAYED) {
276 /* For a relay candidate pair, there may be address translation
277 * between the TURN server and the remote peer, so we cannot trust
278 * XOR-MAPPED-ADDRESS to match our relay address. Traffic continues
279 * to flow via the TURN relay regardless, so just accept the
280 * response as proof that the path works. A peer reflexive
281 * candidate would be wrong here -- it would bypass the relay. */
282 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_SUCCEEDED5);
283 }
284 else if(strlen(pair->stun_client->results.ice_binding_response.mapped_addr.as_string)==0){
285 /* we're using the mapped_addr returned by the server to lookup our
286 * candidate, but if the server fails to do that we can't perform
287 * the lookup -- this may be a BUG because if we've gotten here
288 * then the transaction ID check succeeded, and perhaps we should
289 * just assume that it's the server we're talking to and that our
290 * peer is ok, but I'm not sure how that'll interact with the
291 * peer reflexive logic below */
292 r_log(LOG_ICE,LOG_WARNING4,"ICE-PEER(%s)/CAND-PAIR(%s): server failed to return mapped address on pair %s", pair->pctx->label,pair->codeword,pair->as_string);
293 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
294 break;
295 }
296 else if(!nr_transport_addr_cmp(&pair->local->addr,&pair->stun_client->results.ice_binding_response.mapped_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL4)){
297 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_SUCCEEDED5);
298 }
299 else if(pair->stun_client->state == NR_STUN_CLIENT_STATE_DONE2) {
300 if (pair->local->stream->obsolete) {
301 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/CAND-PAIR(%s): ignore mapped address %s for obsolete stream on pair %s",pair->pctx->label,pair->codeword,pair->stun_client->results.ice_binding_response.mapped_addr.as_string,pair->as_string);
302 goto done;
303 }
304
305 /* OK, this didn't correspond to a pair on the check list, but
306 it probably matches one of our candidates */
307
308 cand=TAILQ_FIRST(&pair->local->component->candidates)((&pair->local->component->candidates)->tqh_first
)
;
309 while(cand){
310 if(!nr_transport_addr_cmp(&cand->addr,&pair->stun_client->results.ice_binding_response.mapped_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL4)) {
311 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): found pre-existing local candidate of type %d for mapped address %s", pair->pctx->label,cand->type,cand->addr.as_string);
312 assert(cand->type != HOST)(static_cast <bool> (cand->type != HOST) ? void (0) :
__assert_fail ("cand->type != HOST", __builtin_FILE (), __builtin_LINE
(), __extension__ __PRETTY_FUNCTION__))
;
313 break;
314 }
315
316 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
317 }
318
319 if(!cand) {
320 /* OK, nothing found, must be a new peer reflexive */
321 if (pair->local->stream->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY(1<<2)) {
322 /* Any STUN response with a reflexive address in it is unwanted
323 when we'll send on relay only. Bail since cand is used below. */
324 goto done;
325 }
326 if(r=nr_ice_candidate_create(pair->pctx->ctx,
327 pair->local->component,pair->local->isock,pair->local->osock,
328 PEER_REFLEXIVE,pair->local->tcp_type,0,pair->local->component->component_id,&cand))
329 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
330 if(r=nr_transport_addr_copy(&cand->addr,&pair->stun_client->results.ice_binding_response.mapped_addr))
331 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
332 cand->state=NR_ICE_CAND_STATE_INITIALIZED3;
333 TAILQ_INSERT_TAIL(&pair->local->component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = __null; (cand)->
entry_comp.tqe_prev = (&pair->local->component->
candidates)->tqh_last; *(&pair->local->component
->candidates)->tqh_last = (cand); (&pair->local->
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
334 } else {
335 /* Check if we have a pair for this candidate already. */
336 if(r=nr_ice_media_stream_find_pair(pair->remote->stream, cand, pair->remote, &actual_pair)) {
337 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): no pair exists for %s and %s", pair->pctx->label,cand->addr.as_string, pair->remote->addr.as_string);
338 }
339 }
340
341 if(!actual_pair) {
342 if(r=nr_ice_candidate_pair_create(pair->pctx,cand,pair->remote, &actual_pair))
343 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
344
345 if(r=nr_ice_socket_register_stun_client(actual_pair->local->isock,
346 actual_pair->stun_client,&actual_pair->stun_client_handle))
347 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
348
349 if(r=nr_ice_component_insert_pair(actual_pair->remote->component,actual_pair))
350 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
351
352 /* If the original pair was nominated, make us nominated too. */
353 if(pair->peer_nominated)
354 actual_pair->peer_nominated=1;
355
356 /* Now mark the orig pair failed */
357 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
358 }
359
360 assert(actual_pair)(static_cast <bool> (actual_pair) ? void (0) : __assert_fail
("actual_pair", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
361 nr_ice_candidate_pair_set_state(actual_pair->pctx,actual_pair,NR_ICE_PAIR_STATE_SUCCEEDED5);
362 pair=actual_pair;
363
364 }
365
366 /* Should we set nominated? */
367 if(pair->pctx->controlling){
368 if(use_candidate)
369 pair->nominated=1;
370 }
371 else{
372 if(pair->peer_nominated)
373 pair->nominated=1;
374 }
375
376
377 /* increment the number of valid pairs in the component */
378 /* We don't bother to maintain a separate valid list */
379 pair->remote->component->valid_pairs++;
380
381 /* S 7.1.2.2: unfreeze other pairs with the same foundation*/
382 if(r=nr_ice_media_stream_unfreeze_pairs_foundation(pair->remote->stream,pair->foundation))
383 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
384
385 /* Deal with this pair being nominated */
386 if(pair->nominated){
387 if(r=nr_ice_component_nominated_pair(pair->remote->component, pair))
388 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
389 }
390
391 break;
392 default:
393 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
394 }
395
396 /* If we're controlling but in regular mode, ask the handler
397 if he wants to nominate something and stop... */
398 if(pair->pctx->controlling && !nr_ice_peer_ctx_aggressive_nomination(pair->pctx)){
399 nr_ice_component_maybe_select_pair(pair->pctx,pair->remote->component);
400 }
401
402 done:
403 _status=0;
404 abort:
405 if (_status) {
406 // cb doesn't return anything, but we should probably log that we aborted
407 // This also quiets the unused variable warnings.
408 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s): STUN cb pair addr = %s abort with status: %d",
409 pair->pctx->label,pair->local->stream->label,pair->codeword,pair->as_string, _status);
410 }
411 return;
412 }
413
414static void nr_ice_candidate_pair_stun_timer_cb(NR_SOCKET s, int how, void *cb_arg)
415 {
416 nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg;
417
418 pair->stun_cb_timer=0;
419 nr_ice_candidate_pair_stun_cb(s,how,cb_arg);
420 }
421
422static void nr_ice_candidate_pair_restart(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
423 {
424 int r,_status;
425 UINT4 mode;
426
427 nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_IN_PROGRESS3);
428
429 /* Start STUN */
430 if(pair->pctx->controlling && nr_ice_peer_ctx_aggressive_nomination(pair->pctx))
431 mode=NR_ICE_CLIENT_MODE_USE_CANDIDATE10;
432 else
433 mode=NR_ICE_CLIENT_MODE_BINDING_REQUEST11;
434
435 nr_stun_client_reset(pair->stun_client);
436
437 if(r=nr_stun_client_start(pair->stun_client,mode,nr_ice_candidate_pair_stun_cb,pair))
438 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
439
440 if ((r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))) {
441 /* ignore if this fails (which it shouldn't) because it's only an
442 * optimization and the cleanup routines are not going to do the right
443 * thing if this fails */
444 assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
445 }
446
447 _status=0;
448 abort:
449 if(_status){
450 /* Don't fire the CB, but schedule it to fire ASAP */
451 NR_async_timer_cancel(pair->stun_cb_timer);
452 pair->stun_cb_timer=0;
453 NR_ASYNC_TIMER_SET(0,nr_ice_candidate_pair_stun_timer_cb,pair, &pair->stun_cb_timer)NR_async_timer_set(0,nr_ice_candidate_pair_stun_timer_cb,pair
,(char *)__FUNCTION__,453,&pair->stun_cb_timer)
;
454 _status=0;
455 }
456 }
457
458int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
459 {
460 int r,_status;
461
462 /* Register the stun ctx for when responses come in*/
463 if(r=nr_ice_socket_register_stun_client(pair->local->isock,pair->stun_client,&pair->stun_client_handle))
464 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
465
466 nr_ice_candidate_pair_restart(pctx, pair);
467
468 _status=0;
469 abort:
470 return(_status);
471 }
472
473static int nr_ice_candidate_copy_for_triggered_check(nr_ice_cand_pair *pair)
474 {
475 int r,_status;
476 nr_ice_cand_pair *copy;
477
478 if(r=nr_ice_candidate_pair_create(pair->pctx, pair->local, pair->remote, &copy))
479 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
480
481 /* Preserve nomination status */
482 copy->peer_nominated= pair->peer_nominated;
483 copy->nominated = pair->nominated;
484
485 r_log(LOG_ICE,LOG_INFO6,"CAND-PAIR(%s): Adding pair to check list and trigger check queue: %s",pair->codeword,pair->as_string);
486 nr_ice_candidate_pair_insert(&pair->remote->stream->check_list,copy);
487 nr_ice_candidate_pair_trigger_check_append(&pair->remote->stream->trigger_check_queue,copy);
488
489 copy->triggered = 1;
490 nr_ice_candidate_pair_set_state(copy->pctx,copy,NR_ICE_PAIR_STATE_WAITING2);
491
492 _status=0;
493 abort:
494 return(_status);
495}
496
497int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int force)
498 {
499 int r,_status;
500
501 if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED5) {
502 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/CAND_PAIR(%s): No new trigger check for succeeded pair",pctx->label,pair->codeword);
503 return(0);
504 } else if (pair->local->stream->obsolete) {
505 r_log(LOG_ICE, LOG_DEBUG7,
506 "ICE-PEER(%s)/CAND_PAIR(%s): No new trigger check for pair with "
507 "obsolete stream",
508 pctx->label, pair->codeword);
509 return (0);
510 }
511
512 /* Do not run this logic more than once on a given pair (|force| is set
513 * when the check we received has USE-CANDIDATE for this pair for the first
514 * time, and this pair is a higher priority than anything that has been
515 * nominated so far) */
516 if(!pair->triggered || force){
517 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/CAND-PAIR(%s): triggered check on %s",pctx->label,pair->codeword,pair->as_string);
518
519 pair->triggered=1;
520
521 switch(pair->state){
522 case NR_ICE_PAIR_STATE_FAILED4:
523 /* OK, there was a pair, it's just invalid: According to Section
524 * 7.2.1.4, we need to resurrect it */
525 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/CAND-PAIR(%s): received STUN check on failed pair, resurrecting: %s",pctx->label,pair->codeword,pair->as_string);
526 [[fallthrough]];
527 case NR_ICE_PAIR_STATE_FROZEN1:
528 nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING2);
529 [[fallthrough]];
530 case NR_ICE_PAIR_STATE_WAITING2:
531 /* Append it additionally to the trigger check queue */
532 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/CAND-PAIR(%s): Inserting pair to trigger check queue: %s",pctx->label,pair->codeword,pair->as_string);
533 nr_ice_candidate_pair_trigger_check_append(&pair->remote->stream->trigger_check_queue,pair);
534 break;
535 case NR_ICE_PAIR_STATE_CANCELLED6:
536 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/CAND-PAIR(%s): received STUN check on cancelled pair, resurrecting: %s",pctx->label,pair->codeword,pair->as_string);
537 [[fallthrough]];
538 case NR_ICE_PAIR_STATE_IN_PROGRESS3:
539 /* Instead of trying to maintain two stun contexts on the same pair,
540 * and handling heterogenous responses and error conditions, we instead
541 * create a second pair that is identical except that it has the
542 * |triggered| bit set. We also cancel the original pair, but it can
543 * still succeed on its own in the special waiting state. */
544 if(r=nr_ice_candidate_copy_for_triggered_check(pair))
545 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
546 nr_ice_candidate_pair_cancel(pair->pctx,pair,1);
547 break;
548 default:
549 /* all states are handled - a new/unknown state should not
550 * automatically enter the start_checks() below */
551 assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
552 break;
553 }
554
555 /* Ensure that the timers are running to start checks on the topmost entry
556 * of the triggered check queue. */
557 if(r=nr_ice_media_stream_start_checks(pair->pctx,pair->remote->stream))
558 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
559 }
560
561 _status=0;
562 abort:
563 return(_status);
564 }
565
566void nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state)
567 {
568 if(pair->restart_nominated_cb_timer){
569 NR_async_timer_cancel(pair->restart_nominated_cb_timer);
570 pair->restart_nominated_cb_timer=0;
571 }
572
573 if(pair->state != NR_ICE_PAIR_STATE_FAILED4){
574 /* If it's already running we need to terminate the stun */
575 if(pair->state==NR_ICE_PAIR_STATE_IN_PROGRESS3){
576 if(move_to_wait_state) {
577 nr_stun_client_wait(pair->stun_client);
578 } else {
579 nr_stun_client_cancel(pair->stun_client);
580 }
581 }
582 nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_CANCELLED6);
583 }
584 }
585
586void nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state)
587 {
588 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/CAND-PAIR(%s): setting pair to state %s: %s",
589 pctx->label,pair->codeword,nr_ice_cand_pair_states[state],pair->as_string);
590
591 /* NOTE: This function used to reference pctx->state instead of
592 pair->state and the assignment to pair->state was at the top
593 of this function. Because pctx->state was never changed, this seems to have
594 been a typo. The natural logic is "if the state changed
595 decrement the counter" so this implies we should be checking
596 the pair state rather than the pctx->state.
597
598 This didn't cause big problems because waiting_pairs was only
599 used for pacing, so the pacing just was kind of broken.
600
601 This note is here as a reminder until we do more testing
602 and make sure that in fact this was a typo.
603 */
604 if(pair->state!=NR_ICE_PAIR_STATE_WAITING2){
605 if(state==NR_ICE_PAIR_STATE_WAITING2)
606 pctx->waiting_pairs++;
607 }
608 else{
609 if(state!=NR_ICE_PAIR_STATE_WAITING2)
610 pctx->waiting_pairs--;
611
612 assert(pctx->waiting_pairs>=0)(static_cast <bool> (pctx->waiting_pairs>=0) ? void
(0) : __assert_fail ("pctx->waiting_pairs>=0", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__))
;
613 }
614 pair->state=state;
615
616
617 if(pair->state==NR_ICE_PAIR_STATE_FAILED4 ||
618 pair->state==NR_ICE_PAIR_STATE_CANCELLED6){
619 nr_ice_component_failed_pair(pair->remote->component, pair);
620 }
621 }
622
623void nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, int log_level)
624 {
625 r_log(LOG_ICE,log_level,"CAND-PAIR(%s): pair %s: state=%s, priority=0x%llx\n",pair->codeword,pair->as_string,nr_ice_cand_pair_states[pair->state],pair->priority);
626 }
627
628
629int nr_ice_candidate_pair_trigger_check_append(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair)
630 {
631 nr_ice_cand_pair *p1 = 0, *p2 = 0;
632 TAILQ_FOREACH_SAFE(p1, head, triggered_check_queue_entry, p2)for ((p1) = (((head))->tqh_first); (p1) && ((p2) =
(((p1))->triggered_check_queue_entry.tqe_next), 1); (p1) =
(p2))
{
633 if (p1 == pair) {
634 return(0);
635 }
636 }
637
638 TAILQ_INSERT_TAIL(head,pair,triggered_check_queue_entry)do { (((pair))->triggered_check_queue_entry.tqe_next) = __null
; (pair)->triggered_check_queue_entry.tqe_prev = (head)->
tqh_last; *(head)->tqh_last = (pair); (head)->tqh_last =
&(((pair))->triggered_check_queue_entry.tqe_next); ; ;
} while (0)
;
639
640 return(0);
641 }
642
643void nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair)
644 {
645 nr_ice_cand_pair *c1;
646
647 c1=TAILQ_FIRST(head)((head)->tqh_first);
648 while(c1){
649 if(c1->priority < pair->priority){
650 TAILQ_INSERT_BEFORE(c1,pair,check_queue_entry)do { (pair)->check_queue_entry.tqe_prev = (c1)->check_queue_entry
.tqe_prev; (((pair))->check_queue_entry.tqe_next) = (c1); *
(c1)->check_queue_entry.tqe_prev = (pair); (c1)->check_queue_entry
.tqe_prev = &(((pair))->check_queue_entry.tqe_next); ;
; } while (0)
;
651 break;
652 }
653
654 c1=TAILQ_NEXT(c1,check_queue_entry)((c1)->check_queue_entry.tqe_next);
655 }
656 if(!c1) TAILQ_INSERT_TAIL(head,pair,check_queue_entry)do { (((pair))->check_queue_entry.tqe_next) = __null; (pair
)->check_queue_entry.tqe_prev = (head)->tqh_last; *(head
)->tqh_last = (pair); (head)->tqh_last = &(((pair))
->check_queue_entry.tqe_next); ; ; } while (0)
;
657 }
658
659int nr_ice_candidate_pair_nominate(nr_ice_cand_pair *pair, UINT4 delay)
660 {
661 nr_ice_cand_pair *pending;
662 nr_ice_component *component=pair->remote->component;
663 bool already_nominated=false;
664
665 if(pair->state != NR_ICE_PAIR_STATE_SUCCEEDED5)
666 return(R_BAD_ARGS6);
667
668 if(component->nominated)
669 return(R_ALREADY4);
670
671 TAILQ_FOREACH(pending,&pair->remote->stream->check_list,check_queue_entry)for ((pending) = (((&pair->remote->stream->check_list
))->tqh_first); (pending); (pending) = (((pending))->check_queue_entry
.tqe_next))
{
672 if(pending->remote->component != component)
673 continue;
674
675 if(pending->nominated ||
676 (pending->state == NR_ICE_PAIR_STATE_IN_PROGRESS3 &&
677 pending->stun_client->mode == NR_ICE_CLIENT_MODE_USE_CANDIDATE10))
678 already_nominated=true;
679
680 /* Replace pending nominations, or cancel them if one already started. */
681 if(pending->restart_nominated_cb_timer){
682 NR_async_timer_cancel(pending->restart_nominated_cb_timer);
683 pending->restart_nominated_cb_timer=0;
684 }
685 }
686
687 if(already_nominated)
688 return(R_ALREADY4);
689
690 return(NR_ASYNC_TIMER_SET(delay,nr_ice_candidate_pair_restart_stun_nominated_cb,NR_async_timer_set(delay,nr_ice_candidate_pair_restart_stun_nominated_cb
,pair,(char *)__FUNCTION__,691,&pair->restart_nominated_cb_timer
)
691 pair,&pair->restart_nominated_cb_timer)NR_async_timer_set(delay,nr_ice_candidate_pair_restart_stun_nominated_cb
,pair,(char *)__FUNCTION__,691,&pair->restart_nominated_cb_timer
)
);
692 }
693
694static void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg)
695 {
696 nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg;
697 int r,_status;
698
699 pair->restart_nominated_cb_timer=0;
700
701 if(pair->state != NR_ICE_PAIR_STATE_SUCCEEDED5 ||
702 !pair->pctx->controlling || pair->local->stream->obsolete)
703 return;
704
705 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_IN_PROGRESS3);
706
707 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s)/COMP(%d): Restarting pair as nominated: %s",pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id,pair->as_string);
708
709 nr_stun_client_reset(pair->stun_client);
710
711 if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_USE_CANDIDATE10,nr_ice_candidate_pair_stun_cb,pair))
712 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
713
714 if((r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request)))
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
715 assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
716
717 _status=0;
718 abort:
719 if (_status) {
720 // cb doesn't return anything, but we should probably log that we aborted
721 // This also quiets the unused variable warnings.
722 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s)/COMP(%d): STUN nominated cb pair as nominated: %s abort with status: %d",
723 pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id,pair->as_string, _status);
724 if(pair->state==NR_ICE_PAIR_STATE_IN_PROGRESS3){
725 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
726 if(pair->pctx->controlling &&
727 !nr_ice_peer_ctx_aggressive_nomination(pair->pctx)){
728 r_log(LOG_ICE,LOG_ERR3,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s)/COMP(%d): Nomination failed to start; asking the application to select another pair",pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id);
729 nr_ice_component_maybe_select_pair(pair->pctx,pair->remote->component);
730 }
731 }
732 }
733 return;
734 }
735
736static void nr_ice_candidate_pair_restart_stun_role_change_cb(NR_SOCKET s, int how, void *cb_arg)
737 {
738 nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg;
739
740 pair->restart_role_change_cb_timer=0;
741
742 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s):COMP(%d): Restarting pair as %s: %s",pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id,pair->pctx->controlling ? "CONTROLLING" : "CONTROLLED",pair->as_string);
743
744 nr_ice_candidate_pair_restart(pair->pctx, pair);
745 }
746
747void nr_ice_candidate_pair_role_change(nr_ice_cand_pair *pair)
748 {
749 pair->stun_client->params.ice_binding_request.control = pair->pctx->controlling ? NR_ICE_CONTROLLING1 : NR_ICE_CONTROLLED2;
750 nr_ice_candidate_pair_set_priority(pair);
751
752 if(pair->state == NR_ICE_PAIR_STATE_IN_PROGRESS3) {
753 /* We could try only restarting in-progress pairs when they receive their
754 * 487, but this ends up being simpler, because any extra 487 are dropped.
755 */
756 if(!pair->restart_role_change_cb_timer)
757 NR_ASYNC_TIMER_SET(0,nr_ice_candidate_pair_restart_stun_role_change_cb,pair,&pair->restart_role_change_cb_timer)NR_async_timer_set(0,nr_ice_candidate_pair_restart_stun_role_change_cb
,pair,(char *)__FUNCTION__,757,&pair->restart_role_change_cb_timer
)
;
758 }
759 }
760
761void nr_ice_candidate_pair_update_rtt(nr_ice_cand_pair *pair, UINT8 rtt_ms)
762 {
763 assert(pair)(static_cast <bool> (pair) ? void (0) : __assert_fail (
"pair", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
764
765 pair->responses_recvd++;
766 pair->current_rtt_ms = rtt_ms;
767 pair->total_rtt_ms += rtt_ms;
768 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/CAND-PAIR(%s): responses_recvd %llu, current_rtt_ms %llu ms, total_rtt_ms %llu ms",
769 pair->pctx->label,pair->codeword,pair->responses_recvd,pair->current_rtt_ms,pair->total_rtt_ms);
770 }
771
772static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
773 nr_ice_candidate *lcand, nr_ice_candidate *rcand)
774 {
775 char as_string[2048];
776
777 snprintf(as_string,
778 sizeof(as_string),
779 "%s|%s(%s|%s)",
780 lcand->addr.as_string,
781 rcand->addr.as_string,
782 lcand->label,
783 rcand->label);
784
785 nr_ice_compute_codeword(as_string,strlen(as_string),pair->codeword);
786 }
787