Bug Summary

File:root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_candidate_pair.cpp
Warning:line 429, column 10
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_STUND_0_96 -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-09-01-224014-2642839-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 pair->stun_cb_timer=0;
225
226 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s): STUN cb on pair addr = %s",
227 pair->pctx->label,pair->local->stream->label,pair->codeword,pair->as_string);
228
229 /* This ordinarily shouldn't happen, but can if we're
230 doing the second check to confirm nomination.
231 Just bail out */
232 if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED5)
233 goto done;
234
235 switch(pair->stun_client->state){
236 case NR_STUN_CLIENT_STATE_FAILED3:
237 sres=pair->stun_client->response;
238 if(sres && nr_stun_message_has_attribute(sres,NR_STUN_ATTR_ERROR_CODE0x0009,&attr)&&attr->u.error_code.number==487){
239
240 /*
241 * Flip the controlling bit; subsequent 487s for other pairs will be
242 * ignored, since we abandon their STUN transactions.
243 */
244 nr_ice_peer_ctx_switch_controlling_role(pair->pctx);
245
246 return;
247 }
248 [[fallthrough]];
249 case NR_STUN_CLIENT_STATE_TIMED_OUT4:
250 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
251 break;
252 case NR_STUN_CLIENT_STATE_DONE2:
253 /* make sure the addresses match up S 7.1.2.2 */
254 response_src=&pair->stun_client->peer_addr;
255 request_dst=&pair->remote->addr;
256 if (nr_transport_addr_cmp(response_src,request_dst,NR_TRANSPORT_ADDR_CMP_MODE_ALL4)){
257 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);
258 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
259 break;
260 }
261 request_src=&pair->stun_client->my_addr;
262 nr_socket_getaddr(pair->local->osock,&response_dst);
263 if (nr_transport_addr_cmp(request_src,&response_dst,NR_TRANSPORT_ADDR_CMP_MODE_ALL4)){
264 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);
265 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
266 break;
267 }
268
269 // Update the rtt related fields
270 if (pair->stun_client->rtt_valid) {
271 nr_ice_candidate_pair_update_rtt(pair, pair->stun_client->rtt_ms);
272 // clear rtt_ms so we can't double process it.
273 pair->stun_client->rtt_valid = 0;
274 pair->stun_client->rtt_ms = 0;
275 }
276
277 if (pair->local->type == RELAYED) {
278 /* For a relay candidate pair, there may be address translation
279 * between the TURN server and the remote peer, so we cannot trust
280 * XOR-MAPPED-ADDRESS to match our relay address. Traffic continues
281 * to flow via the TURN relay regardless, so just accept the
282 * response as proof that the path works. A peer reflexive
283 * candidate would be wrong here -- it would bypass the relay. */
284 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_SUCCEEDED5);
285 }
286 else if(strlen(pair->stun_client->results.ice_binding_response.mapped_addr.as_string)==0){
287 /* we're using the mapped_addr returned by the server to lookup our
288 * candidate, but if the server fails to do that we can't perform
289 * the lookup -- this may be a BUG because if we've gotten here
290 * then the transaction ID check succeeded, and perhaps we should
291 * just assume that it's the server we're talking to and that our
292 * peer is ok, but I'm not sure how that'll interact with the
293 * peer reflexive logic below */
294 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);
295 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
296 break;
297 }
298 else if(!nr_transport_addr_cmp(&pair->local->addr,&pair->stun_client->results.ice_binding_response.mapped_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL4)){
299 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_SUCCEEDED5);
300 }
301 else if(pair->stun_client->state == NR_STUN_CLIENT_STATE_DONE2) {
302 /* OK, this didn't correspond to a pair on the check list, but
303 it probably matches one of our candidates */
304
305 cand=TAILQ_FIRST(&pair->local->component->candidates)((&pair->local->component->candidates)->tqh_first
)
;
306 while(cand){
307 if(!nr_transport_addr_cmp(&cand->addr,&pair->stun_client->results.ice_binding_response.mapped_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL4)) {
308 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);
309 assert(cand->type != HOST)(static_cast <bool> (cand->type != HOST) ? void (0) :
__assert_fail ("cand->type != HOST", __builtin_FILE (), __builtin_LINE
(), __extension__ __PRETTY_FUNCTION__))
;
310 break;
311 }
312
313 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
314 }
315
316 if(!cand) {
317 /* OK, nothing found, must be a new peer reflexive */
318 if (pair->local->stream->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY(1<<2)) {
319 /* Any STUN response with a reflexive address in it is unwanted
320 when we'll send on relay only. Bail since cand is used below. */
321 goto done;
322 }
323 if(r=nr_ice_candidate_create(pair->pctx->ctx,
324 pair->local->component,pair->local->isock,pair->local->osock,
325 PEER_REFLEXIVE,pair->local->tcp_type,0,pair->local->component->component_id,&cand))
326 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
327 if(r=nr_transport_addr_copy(&cand->addr,&pair->stun_client->results.ice_binding_response.mapped_addr))
328 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
329 cand->state=NR_ICE_CAND_STATE_INITIALIZED3;
330 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)
;
331 } else {
332 /* Check if we have a pair for this candidate already. */
333 if(r=nr_ice_media_stream_find_pair(pair->remote->stream, cand, pair->remote, &actual_pair)) {
334 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);
335 }
336 }
337
338 if(!actual_pair) {
339 if(r=nr_ice_candidate_pair_create(pair->pctx,cand,pair->remote, &actual_pair))
340 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
341
342 if(r=nr_ice_socket_register_stun_client(actual_pair->local->isock,
343 actual_pair->stun_client,&actual_pair->stun_client_handle))
344 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
345
346 if(r=nr_ice_component_insert_pair(actual_pair->remote->component,actual_pair))
347 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
348
349 /* If the original pair was nominated, make us nominated too. */
350 if(pair->peer_nominated)
351 actual_pair->peer_nominated=1;
352
353 /* Now mark the orig pair failed */
354 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
355 }
356
357 assert(actual_pair)(static_cast <bool> (actual_pair) ? void (0) : __assert_fail
("actual_pair", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
358 nr_ice_candidate_pair_set_state(actual_pair->pctx,actual_pair,NR_ICE_PAIR_STATE_SUCCEEDED5);
359 pair=actual_pair;
360
361 }
362
363 /* Should we set nominated? */
364 if(pair->pctx->controlling){
365 if(use_candidate)
366 pair->nominated=1;
367 }
368 else{
369 if(pair->peer_nominated)
370 pair->nominated=1;
371 }
372
373
374 /* increment the number of valid pairs in the component */
375 /* We don't bother to maintain a separate valid list */
376 pair->remote->component->valid_pairs++;
377
378 /* S 7.1.2.2: unfreeze other pairs with the same foundation*/
379 if(r=nr_ice_media_stream_unfreeze_pairs_foundation(pair->remote->stream,pair->foundation))
380 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
381
382 /* Deal with this pair being nominated */
383 if(pair->nominated){
384 if(r=nr_ice_component_nominated_pair(pair->remote->component, pair))
385 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
386 }
387
388 break;
389 default:
390 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
391 }
392
393 /* If we're controlling but in regular mode, ask the handler
394 if he wants to nominate something and stop... */
395 if(pair->pctx->controlling && !nr_ice_peer_ctx_aggressive_nomination(pair->pctx)){
396 nr_ice_component_maybe_select_pair(pair->pctx,pair->remote->component);
397 }
398
399 done:
400 _status=0;
401 abort:
402 if (_status) {
403 // cb doesn't return anything, but we should probably log that we aborted
404 // This also quiets the unused variable warnings.
405 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s): STUN cb pair addr = %s abort with status: %d",
406 pair->pctx->label,pair->local->stream->label,pair->codeword,pair->as_string, _status);
407 }
408 return;
409 }
410
411static void nr_ice_candidate_pair_restart(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
412 {
413 int r,_status;
414 UINT4 mode;
415
416 nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_IN_PROGRESS3);
417
418 /* Start STUN */
419 if(pair->pctx->controlling && nr_ice_peer_ctx_aggressive_nomination(pair->pctx))
420 mode=NR_ICE_CLIENT_MODE_USE_CANDIDATE10;
421 else
422 mode=NR_ICE_CLIENT_MODE_BINDING_REQUEST11;
423
424 nr_stun_client_reset(pair->stun_client);
425
426 if(r=nr_stun_client_start(pair->stun_client,mode,nr_ice_candidate_pair_stun_cb,pair))
427 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
428
429 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'
430 /* ignore if this fails (which it shouldn't) because it's only an
431 * optimization and the cleanup routines are not going to do the right
432 * thing if this fails */
433 assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
434 }
435
436 _status=0;
437 abort:
438 if(_status){
439 /* Don't fire the CB, but schedule it to fire ASAP */
440 assert(!pair->stun_cb_timer)(static_cast <bool> (!pair->stun_cb_timer) ? void (0
) : __assert_fail ("!pair->stun_cb_timer", __builtin_FILE (
), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__))
;
441 NR_ASYNC_TIMER_SET(0,nr_ice_candidate_pair_stun_cb,pair, &pair->stun_cb_timer)NR_async_timer_set(0,nr_ice_candidate_pair_stun_cb,pair,(char
*)__FUNCTION__,441,&pair->stun_cb_timer)
;
442 _status=0;
443 }
444 }
445
446int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
447 {
448 int r,_status;
449
450 /* Register the stun ctx for when responses come in*/
451 if(r=nr_ice_socket_register_stun_client(pair->local->isock,pair->stun_client,&pair->stun_client_handle))
452 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
453
454 nr_ice_candidate_pair_restart(pctx, pair);
455
456 _status=0;
457 abort:
458 return(_status);
459 }
460
461static int nr_ice_candidate_copy_for_triggered_check(nr_ice_cand_pair *pair)
462 {
463 int r,_status;
464 nr_ice_cand_pair *copy;
465
466 if(r=nr_ice_candidate_pair_create(pair->pctx, pair->local, pair->remote, &copy))
467 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
468
469 /* Preserve nomination status */
470 copy->peer_nominated= pair->peer_nominated;
471 copy->nominated = pair->nominated;
472
473 r_log(LOG_ICE,LOG_INFO6,"CAND-PAIR(%s): Adding pair to check list and trigger check queue: %s",pair->codeword,pair->as_string);
474 nr_ice_candidate_pair_insert(&pair->remote->stream->check_list,copy);
475 nr_ice_candidate_pair_trigger_check_append(&pair->remote->stream->trigger_check_queue,copy);
476
477 copy->triggered = 1;
478 nr_ice_candidate_pair_set_state(copy->pctx,copy,NR_ICE_PAIR_STATE_WAITING2);
479
480 _status=0;
481 abort:
482 return(_status);
483}
484
485int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int force)
486 {
487 int r,_status;
488
489 if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED5) {
490 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/CAND_PAIR(%s): No new trigger check for succeeded pair",pctx->label,pair->codeword);
491 return(0);
492 } else if (pair->local->stream->obsolete) {
493 r_log(LOG_ICE, LOG_DEBUG7,
494 "ICE-PEER(%s)/CAND_PAIR(%s): No new trigger check for pair with "
495 "obsolete stream",
496 pctx->label, pair->codeword);
497 return (0);
498 }
499
500 /* Do not run this logic more than once on a given pair (|force| is set
501 * when the check we received has USE-CANDIDATE for this pair for the first
502 * time, and this pair is a higher priority than anything that has been
503 * nominated so far) */
504 if(!pair->triggered || force){
505 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/CAND-PAIR(%s): triggered check on %s",pctx->label,pair->codeword,pair->as_string);
506
507 pair->triggered=1;
508
509 switch(pair->state){
510 case NR_ICE_PAIR_STATE_FAILED4:
511 /* OK, there was a pair, it's just invalid: According to Section
512 * 7.2.1.4, we need to resurrect it */
513 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);
514 [[fallthrough]];
515 case NR_ICE_PAIR_STATE_FROZEN1:
516 nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING2);
517 [[fallthrough]];
518 case NR_ICE_PAIR_STATE_WAITING2:
519 /* Append it additionally to the trigger check queue */
520 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);
521 nr_ice_candidate_pair_trigger_check_append(&pair->remote->stream->trigger_check_queue,pair);
522 break;
523 case NR_ICE_PAIR_STATE_CANCELLED6:
524 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);
525 [[fallthrough]];
526 case NR_ICE_PAIR_STATE_IN_PROGRESS3:
527 /* Instead of trying to maintain two stun contexts on the same pair,
528 * and handling heterogenous responses and error conditions, we instead
529 * create a second pair that is identical except that it has the
530 * |triggered| bit set. We also cancel the original pair, but it can
531 * still succeed on its own in the special waiting state. */
532 if(r=nr_ice_candidate_copy_for_triggered_check(pair))
533 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
534 nr_ice_candidate_pair_cancel(pair->pctx,pair,1);
535 break;
536 default:
537 /* all states are handled - a new/unknown state should not
538 * automatically enter the start_checks() below */
539 assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
540 break;
541 }
542
543 /* Ensure that the timers are running to start checks on the topmost entry
544 * of the triggered check queue. */
545 if(r=nr_ice_media_stream_start_checks(pair->pctx,pair->remote->stream))
546 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
547 }
548
549 _status=0;
550 abort:
551 return(_status);
552 }
553
554void nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state)
555 {
556 if(pair->restart_nominated_cb_timer){
557 NR_async_timer_cancel(pair->restart_nominated_cb_timer);
558 pair->restart_nominated_cb_timer=0;
559 }
560
561 if(pair->state != NR_ICE_PAIR_STATE_FAILED4){
562 /* If it's already running we need to terminate the stun */
563 if(pair->state==NR_ICE_PAIR_STATE_IN_PROGRESS3){
564 if(move_to_wait_state) {
565 nr_stun_client_wait(pair->stun_client);
566 } else {
567 nr_stun_client_cancel(pair->stun_client);
568 }
569 }
570 nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_CANCELLED6);
571 }
572 }
573
574void nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state)
575 {
576 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/CAND-PAIR(%s): setting pair to state %s: %s",
577 pctx->label,pair->codeword,nr_ice_cand_pair_states[state],pair->as_string);
578
579 /* NOTE: This function used to reference pctx->state instead of
580 pair->state and the assignment to pair->state was at the top
581 of this function. Because pctx->state was never changed, this seems to have
582 been a typo. The natural logic is "if the state changed
583 decrement the counter" so this implies we should be checking
584 the pair state rather than the pctx->state.
585
586 This didn't cause big problems because waiting_pairs was only
587 used for pacing, so the pacing just was kind of broken.
588
589 This note is here as a reminder until we do more testing
590 and make sure that in fact this was a typo.
591 */
592 if(pair->state!=NR_ICE_PAIR_STATE_WAITING2){
593 if(state==NR_ICE_PAIR_STATE_WAITING2)
594 pctx->waiting_pairs++;
595 }
596 else{
597 if(state!=NR_ICE_PAIR_STATE_WAITING2)
598 pctx->waiting_pairs--;
599
600 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__))
;
601 }
602 pair->state=state;
603
604
605 if(pair->state==NR_ICE_PAIR_STATE_FAILED4 ||
606 pair->state==NR_ICE_PAIR_STATE_CANCELLED6){
607 nr_ice_component_failed_pair(pair->remote->component, pair);
608 }
609 }
610
611void nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, int log_level)
612 {
613 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);
614 }
615
616
617int nr_ice_candidate_pair_trigger_check_append(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair)
618 {
619 nr_ice_cand_pair *p1 = 0, *p2 = 0;
620 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))
{
621 if (p1 == pair) {
622 return(0);
623 }
624 }
625
626 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)
;
627
628 return(0);
629 }
630
631void nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair)
632 {
633 nr_ice_cand_pair *c1;
634
635 c1=TAILQ_FIRST(head)((head)->tqh_first);
636 while(c1){
637 if(c1->priority < pair->priority){
638 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)
;
639 break;
640 }
641
642 c1=TAILQ_NEXT(c1,check_queue_entry)((c1)->check_queue_entry.tqe_next);
643 }
644 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)
;
645 }
646
647int nr_ice_candidate_pair_nominate(nr_ice_cand_pair *pair, UINT4 delay)
648 {
649 nr_ice_cand_pair *pending;
650 nr_ice_component *component=pair->remote->component;
651 bool already_nominated=false;
652
653 if(pair->state != NR_ICE_PAIR_STATE_SUCCEEDED5)
654 return(R_BAD_ARGS6);
655
656 if(component->nominated)
657 return(R_ALREADY4);
658
659 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))
{
660 if(pending->remote->component != component)
661 continue;
662
663 if(pending->nominated ||
664 (pending->state == NR_ICE_PAIR_STATE_IN_PROGRESS3 &&
665 pending->stun_client->mode == NR_ICE_CLIENT_MODE_USE_CANDIDATE10))
666 already_nominated=true;
667
668 /* Replace pending nominations, or cancel them if one already started. */
669 if(pending->restart_nominated_cb_timer){
670 NR_async_timer_cancel(pending->restart_nominated_cb_timer);
671 pending->restart_nominated_cb_timer=0;
672 }
673 }
674
675 if(already_nominated)
676 return(R_ALREADY4);
677
678 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__,679,&pair->restart_nominated_cb_timer
)
679 pair,&pair->restart_nominated_cb_timer)NR_async_timer_set(delay,nr_ice_candidate_pair_restart_stun_nominated_cb
,pair,(char *)__FUNCTION__,679,&pair->restart_nominated_cb_timer
)
);
680 }
681
682static void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg)
683 {
684 nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg;
685 int r,_status;
686
687 pair->restart_nominated_cb_timer=0;
688
689 if(pair->state != NR_ICE_PAIR_STATE_SUCCEEDED5 ||
690 !pair->pctx->controlling || pair->local->stream->obsolete)
691 return;
692
693 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_IN_PROGRESS3);
694
695 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);
696
697 nr_stun_client_reset(pair->stun_client);
698
699 if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_USE_CANDIDATE10,nr_ice_candidate_pair_stun_cb,pair))
700 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
701
702 if((r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request)))
703 assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
704
705 _status=0;
706 abort:
707 if (_status) {
708 // cb doesn't return anything, but we should probably log that we aborted
709 // This also quiets the unused variable warnings.
710 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",
711 pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id,pair->as_string, _status);
712 if(pair->state==NR_ICE_PAIR_STATE_IN_PROGRESS3){
713 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED4);
714 if(pair->pctx->controlling &&
715 !nr_ice_peer_ctx_aggressive_nomination(pair->pctx)){
716 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);
717 nr_ice_component_maybe_select_pair(pair->pctx,pair->remote->component);
718 }
719 }
720 }
721 return;
722 }
723
724static void nr_ice_candidate_pair_restart_stun_role_change_cb(NR_SOCKET s, int how, void *cb_arg)
725 {
726 nr_ice_cand_pair *pair=(nr_ice_cand_pair*)cb_arg;
727
728 pair->restart_role_change_cb_timer=0;
729
730 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);
731
732 nr_ice_candidate_pair_restart(pair->pctx, pair);
733 }
734
735void nr_ice_candidate_pair_role_change(nr_ice_cand_pair *pair)
736 {
737 pair->stun_client->params.ice_binding_request.control = pair->pctx->controlling ? NR_ICE_CONTROLLING1 : NR_ICE_CONTROLLED2;
738 nr_ice_candidate_pair_set_priority(pair);
739
740 if(pair->state == NR_ICE_PAIR_STATE_IN_PROGRESS3) {
741 /* We could try only restarting in-progress pairs when they receive their
742 * 487, but this ends up being simpler, because any extra 487 are dropped.
743 */
744 if(!pair->restart_role_change_cb_timer)
745 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__,745,&pair->restart_role_change_cb_timer
)
;
746 }
747 }
748
749void nr_ice_candidate_pair_update_rtt(nr_ice_cand_pair *pair, UINT8 rtt_ms)
750 {
751 assert(pair)(static_cast <bool> (pair) ? void (0) : __assert_fail (
"pair", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
752
753 pair->responses_recvd++;
754 pair->current_rtt_ms = rtt_ms;
755 pair->total_rtt_ms += rtt_ms;
756 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",
757 pair->pctx->label,pair->codeword,pair->responses_recvd,pair->current_rtt_ms,pair->total_rtt_ms);
758 }
759
760static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
761 nr_ice_candidate *lcand, nr_ice_candidate *rcand)
762 {
763 char as_string[2048];
764
765 snprintf(as_string,
766 sizeof(as_string),
767 "%s|%s(%s|%s)",
768 lcand->addr.as_string,
769 rcand->addr.as_string,
770 lcand->label,
771 rcand->label);
772
773 nr_ice_compute_codeword(as_string,strlen(as_string),pair->codeword);
774 }
775