/** * Forming Candidate Pairs */ static int candpairs_form(struct icem *icem) { struct le *le; int err = 0; if (list_isempty(&icem->lcandl)) return ENOENT; for (le = icem->lcandl.head; le; le = le->next) { struct cand *lcand = le->data; struct le *rle; for (rle = icem->rcandl.head; rle; rle = rle->next) { struct cand *rcand = rle->data; if (lcand->compid != rcand->compid) continue; if (sa_af(&lcand->addr) != sa_af(&rcand->addr)) continue; err |= icem_candpair_alloc(NULL, icem, lcand, rcand); } } return err; }
/* * 7.2.2. Additional Procedures for Lite Implementations */ static int handle_stun_lite(struct icem *icem, struct icem_comp *comp, const struct sa *src, bool use_cand) { struct cand *lcand, *rcand; struct candpair *cp; int err; if (!use_cand) return 0; rcand = icem_cand_find(&icem->rcandl, comp->id, src); if (!rcand) { DEBUG_WARNING("lite: could not find remote candidate\n"); return 0; } /* find the local host candidate with the same component */ lcand = icem_cand_find(&icem->lcandl, comp->id, NULL); if (!lcand) { DEBUG_WARNING("lite: could not find local candidate\n"); return 0; } /* search validlist for existing candpair's */ if (icem_candpair_find(&icem->validl, lcand, rcand)) return 0; err = icem_candpair_alloc(&cp, icem, lcand, rcand); if (err) { DEBUG_WARNING("lite: failed to created candidate pair\n"); return err; } icem_candpair_make_valid(cp); cp->nominated = true; return 0; }
/** * Forming Candidate Pairs */ static int candpairs_form(struct icem *icem) { struct le *le; int err = 0; if (list_isempty(&icem->lcandl)) return ENOENT; if (list_isempty(&icem->rcandl)) { DEBUG_WARNING("%s: no remote candidates\n", icem->name); return ENOENT; } for (le = icem->lcandl.head; le; le = le->next) { struct cand *lcand = le->data; struct le *rle; for (rle = icem->rcandl.head; rle; rle = rle->next) { struct cand *rcand = rle->data; if (lcand->compid != rcand->compid) continue; if (sa_af(&lcand->addr) != sa_af(&rcand->addr)) continue; err = icem_candpair_alloc(NULL, icem, lcand, rcand); if (err) return err; } } return err; }
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 } }