/** * Stop checklist, cancel all connectivity checks * * @param icem ICE Media object * @param err Error code */ void icem_conncheck_stop(struct icem *icem, int err) { struct le *le; icem->state = err ? ICE_CHECKLIST_FAILED : ICE_CHECKLIST_COMPLETED; tmr_cancel(&icem->tmr_pace); for (le = icem->checkl.head; le; le = le->next) { struct ice_candpair *cp = le->data; if (!icem_candpair_iscompleted(cp)) { icem_candpair_cancel(cp); icem_candpair_failed(cp, EINTR, 0); } } icem_checklist_update(icem); }
static int handle_stun(struct ice *ice, struct icem *icem, struct icem_comp *comp, const struct sa *src, uint32_t prio, bool use_cand, bool tunnel) { struct cand *lcand = NULL, *rcand; struct candpair *cp = NULL; int err; rcand = icem_cand_find(&icem->rcandl, comp->id, src); if (!rcand) { err = icem_rcand_add_prflx(&rcand, icem, comp->id, prio, src); if (err) return err; } cp = icem_candpair_find_rcand(icem, rcand); if (cp) lcand = cp->lcand; else lcand = icem_lcand_find_checklist(icem, comp->id); if (!lcand) { DEBUG_WARNING("{%s.%u} no local candidate" " (checklist=%u) (src=%J)\n", icem->name, comp->id, list_count(&icem->checkl), src); return 0; } if (ICE_MODE_FULL == ice->lmode) triggered_check(icem, lcand, rcand); if (!cp) { cp = icem_candpair_find_rcand(icem, rcand); if (!cp) { DEBUG_WARNING("{%s.%u} candidate pair not found:" " source=%J\n", icem->name, comp->id, src); return 0; } } #if ICE_TRACE icecomp_printf(comp, "Rx Binding Request from %J via %s" " (candpair=%s) %s\n", src, tunnel ? "Tunnel" : "Socket", cp ? ice_candpair_state2name(cp->state) : "n/a", use_cand ? "[USE]" : ""); #else (void)tunnel; #endif /* 7.2.1.5. Updating the Nominated Flag */ if (use_cand) { if (ice->lrole == ROLE_CONTROLLED) { if (cp->state == CANDPAIR_SUCCEEDED) { cp->nominated = true; icecomp_printf(comp, "setting NOMINATED" " flag on candpair [%H]\n", icem_candpair_debug, cp); } } /* Cancel conncheck. Choose Selected Pair */ icem_candpair_make_valid(cp); if (ice->conf.nom == ICE_NOMINATION_REGULAR) { icem_candpair_cancel(cp); icem_comp_set_selected(comp, cp); } } return 0; }
static void triggered_check(struct icem *icem, struct cand *lcand, struct cand *rcand) { struct candpair *cp = NULL; int err; if (lcand && rcand) cp = icem_candpair_find(&icem->checkl, lcand, rcand); if (cp) { icecomp_printf(cp->comp, "triggered_check: found CandidatePair on" " checklist in state: %H\n", icem_candpair_debug, cp); switch (cp->state) { #if 0 /* TODO: I am not sure why we should cancel the * pending Connectivity check here. this * can lead to a deadlock situation where * both agents are stuck on sending * triggered checks on the same candidate pair */ case CANDPAIR_INPROGRESS: icem_candpair_cancel(cp); /*@fallthrough@*/ #endif case CANDPAIR_FAILED: icem_candpair_set_state(cp, CANDPAIR_WAITING); /*@fallthrough@*/ case CANDPAIR_FROZEN: case CANDPAIR_WAITING: err = icem_conncheck_send(cp, false, true); if (err) { DEBUG_WARNING("triggered check failed\n"); } break; case CANDPAIR_SUCCEEDED: default: break; } } else { #if 0 err = icem_candpair_alloc(&cp, icem, lcand, rcand); if (err) { DEBUG_WARNING("failed to allocate candpair:" " lcand=%p rcand=%p (%m)\n", lcand, rcand, err); return; } icem_candpair_prio_order(&icem->checkl); icem_candpair_set_state(cp, CANDPAIR_WAITING); (void)icem_conncheck_send(cp, false, true); #endif } }