From 5af1657c55b69e6666dffa4a964d71ee4704b518 Mon Sep 17 00:00:00 2001 From: Richard Aas Date: Mon, 27 May 2013 13:23:03 +0000 Subject: [PATCH] ice: many improvements and fixes --- include/re_ice.h | 1 + src/ice/cand.c | 35 ++++++++++ src/ice/candpair.c | 55 ++++++++++------ src/ice/chklist.c | 20 +++++- src/ice/comp.c | 28 +------- src/ice/connchk.c | 95 ++++++++++++++------------- src/ice/gather.c | 12 +++- src/ice/ice.c | 23 ++++++- src/ice/ice.h | 10 +-- src/ice/icem.c | 50 ++++++-------- src/ice/icesdp.c | 4 +- src/ice/stunsrv.c | 158 ++++++++++++++++----------------------------- 12 files changed, 256 insertions(+), 235 deletions(-) diff --git a/include/re_ice.h b/include/re_ice.h index a6eb66f..6ecdc57 100644 --- a/include/re_ice.h +++ b/include/re_ice.h @@ -64,6 +64,7 @@ int icem_gather_relay(struct icem *icem, const struct sa *stun_srv, bool icem_verify_support(struct icem *icem, uint8_t compid, const struct sa *raddr); int icem_conncheck_start(struct icem *icem); +void icem_conncheck_stop(struct icem *icem, int err); int icem_add_chan(struct icem *icem, uint8_t compid, const struct sa *raddr); bool icem_mismatch(const struct icem *icem); void icem_update(struct icem *icem); diff --git a/src/ice/cand.c b/src/ice/cand.c index 89000e5..516d1c7 100644 --- a/src/ice/cand.c +++ b/src/ice/cand.c @@ -188,7 +188,14 @@ int icem_rcand_add_prflx(struct cand **rcp, struct icem *icem, uint8_t compid, rcand->addr = *addr; err = re_sdprintf(&rcand->foundation, "%08x", rand_u32()); + if (err) + goto out; + icecomp_printf(icem_comp_find(icem, compid), + "added PeerReflexive remote candidate" + " with priority %u (%J)\n", prio, addr); + + out: if (err) mem_deref(rcand); else if (rcp) @@ -220,6 +227,34 @@ struct cand *icem_cand_find(const struct list *lst, uint8_t compid, } +/** + * Find the highest priority LCAND on the check-list of type HOST/RELAY + */ +struct cand *icem_lcand_find_checklist(const struct icem *icem, uint8_t compid) +{ + struct le *le; + + for (le = icem->checkl.head; le; le = le->next) { + struct candpair *cp = le->data; + + if (cp->lcand->compid != compid) + continue; + + switch (cp->lcand->type) { + + case CAND_TYPE_HOST: + case CAND_TYPE_RELAY: + return cp->lcand; + + default: + break; + } + } + + return NULL; +} + + int icem_cands_debug(struct re_printf *pf, const struct list *lst) { struct le *le; diff --git a/src/ice/candpair.c b/src/ice/candpair.c index 415cbac..f280acf 100644 --- a/src/ice/candpair.c +++ b/src/ice/candpair.c @@ -101,7 +101,6 @@ int icem_candpair_alloc(struct candpair **cpp, struct icem *icem, cp->lcand = mem_ref(lcand); cp->rcand = mem_ref(rcand); cp->state = CANDPAIR_FROZEN; - cp->ertt = -1; cp->def = comp->def_lcand == lcand && comp->def_rcand == rcand; candpair_set_pprio(cp); @@ -136,8 +135,6 @@ int icem_candpair_clone(struct candpair **cpp, struct candpair *cp0, cp->nominated = cp0->nominated; cp->state = cp0->state; cp->pprio = cp0->pprio; - cp->usec_sent = cp0->usec_sent; - cp->ertt = cp0->ertt; cp->err = cp0->err; cp->scode = cp0->scode; @@ -184,9 +181,6 @@ void icem_candpair_make_valid(struct candpair *cp) cp->scode = 0; cp->valid = true; - if (cp->usec_sent) - cp->ertt = (long)(ice_get_usec() - cp->usec_sent); - icem_candpair_set_state(cp, CANDPAIR_SUCCEEDED); list_unlink(&cp->le); @@ -211,16 +205,17 @@ void icem_candpair_set_state(struct candpair *cp, enum candpair_state state) { if (!cp) return; + if (cp->state == state || icem_candpair_iscompleted(cp)) + return; - if (cp->state != state) { - icecomp_printf(cp->comp, - "%5s <---> %5s FSM: %10s ===> %-10s\n", - ice_cand_type2name(cp->lcand->type), - ice_cand_type2name(cp->rcand->type), - ice_candpair_state2name(cp->state), - ice_candpair_state2name(state)); - cp->state = state; - } + icecomp_printf(cp->comp, + "%5s <---> %5s FSM: %10s ===> %-10s\n", + ice_cand_type2name(cp->lcand->type), + ice_cand_type2name(cp->rcand->type), + ice_candpair_state2name(cp->state), + ice_candpair_state2name(state)); + + cp->state = state; } @@ -355,6 +350,26 @@ struct candpair *icem_candpair_find_compid(const struct list *lst, } +/** + * Find a remote candidate in the checklist or validlist + */ +struct candpair *icem_candpair_find_rcand(struct icem *icem, + const struct cand *rcand) +{ + struct candpair *cp; + + cp = icem_candpair_find(&icem->checkl, NULL, rcand); + if (cp) + return cp; + + cp = icem_candpair_find(&icem->validl, NULL, rcand); + if (cp) + return cp; + + return NULL; +} + + bool icem_candpair_cmp_fnd(const struct candpair *cp1, const struct candpair *cp2) { @@ -373,7 +388,7 @@ int icem_candpair_debug(struct re_printf *pf, const struct candpair *cp) if (!cp) return 0; - err = re_hprintf(pf, "{%u} %10s {%c%c%c} %28H <---> %28H", + err = re_hprintf(pf, "{comp=%u} %10s {%c%c%c} %28H <---> %28H", cp->lcand->compid, ice_candpair_state2name(cp->state), cp->def ? 'D' : ' ', @@ -382,9 +397,6 @@ int icem_candpair_debug(struct re_printf *pf, const struct candpair *cp) icem_cand_print, cp->lcand, icem_cand_print, cp->rcand); - if (cp->ertt != -1) - err |= re_hprintf(pf, " ERTT = %.2fms", cp->ertt / 1000.0); - if (cp->err) err |= re_hprintf(pf, " (%m)", cp->err); @@ -408,8 +420,11 @@ int icem_candpairs_debug(struct re_printf *pf, const struct list *list) for (le = list->head; le && !err; le = le->next) { const struct candpair *cp = le->data; + bool is_selected = (cp == cp->comp->cp_sel); - err = re_hprintf(pf, " %H\n", icem_candpair_debug, cp); + err = re_hprintf(pf, " %c %H\n", + is_selected ? '*' : ' ', + icem_candpair_debug, cp); } return err; diff --git a/src/ice/chklist.c b/src/ice/chklist.c index 06a2315..002cdbe 100644 --- a/src/ice/chklist.c +++ b/src/ice/chklist.c @@ -32,6 +32,11 @@ static int candpairs_form(struct icem *icem) 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; @@ -47,7 +52,9 @@ static int candpairs_form(struct icem *icem) if (sa_af(&lcand->addr) != sa_af(&rcand->addr)) continue; - err |= icem_candpair_alloc(NULL, icem, lcand, rcand); + err = icem_candpair_alloc(NULL, icem, lcand, rcand); + if (err) + return err; } } @@ -62,10 +69,14 @@ static const struct sa *cand_srflx_addr(const struct cand *c) } +/* return: NULL to keep, pointer to remove object */ static void *unique_handler(struct le *le1, struct le *le2) { struct candpair *cp1 = le1->data, *cp2 = le2->data; + if (cp1->comp->id != cp2->comp->id) + return NULL; + if (!sa_cmp(cand_srflx_addr(cp1->lcand), cand_srflx_addr(cp2->lcand), SA_ALL) || !sa_cmp(&cp1->rcand->addr, &cp2->rcand->addr, SA_ALL)) @@ -236,9 +247,11 @@ static void concluding_ice(struct icem_comp *comp) void icem_checklist_update(struct icem *icem) { struct le *le; + bool compl; int err = 0; - if (!iscompleted(icem)) + compl = iscompleted(icem); + if (!compl) return; /* @@ -268,9 +281,10 @@ void icem_checklist_update(struct icem *icem) icem->state = err ? CHECKLIST_FAILED : CHECKLIST_COMPLETED; - if (icem->chkh) + if (icem->chkh) { icem->chkh(err, icem->ice->lrole == ROLE_CONTROLLING, icem->arg); + } } diff --git a/src/ice/comp.c b/src/ice/comp.c index 52d0458..2d79d27 100644 --- a/src/ice/comp.c +++ b/src/ice/comp.c @@ -27,27 +27,6 @@ enum {COMPID_MIN = 1, COMPID_MAX = 255}; -#if 0 -/* for debugging */ -static bool helper_send_handler(int *err, struct sa *dst, - struct mbuf *mb, void *arg) -{ - struct icem_comp *comp = arg; - - (void)comp; - (void)err; - (void)dst; - (void)mb; - - re_printf("{id=%d} ......... UDP send %u bytes to %J via %s\n", - comp->id, mbuf_get_left(mb), dst, - (mb->pos && comp->turnc) ? "tunnel" : "socket"); - - return false; -} -#endif - - static bool helper_recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct icem_comp *comp = arg; @@ -73,7 +52,7 @@ static bool helper_recv_handler(struct sa *src, struct mbuf *mb, void *arg) break; default: - (void)stun_ctrans_recv(icem->stun, msg, &ua); + (void)stun_ctrans_recv(icem->ice->stun, msg, &ua); break; } } @@ -155,8 +134,7 @@ int icem_comp_alloc(struct icem_comp **cp, struct icem *icem, int id, comp->icem = icem; err = udp_register_helper(&comp->uh, sock, icem->layer, - NULL, /*helper_send_handler*/ - helper_recv_handler, comp); + NULL, helper_recv_handler, comp); if (err) goto out; @@ -290,6 +268,6 @@ void icecomp_printf(struct icem_comp *comp, const char *fmt, ...) return; va_start(ap, fmt); - (void)re_printf("{%s.%u} %v", comp->icem->name, comp->id, fmt, &ap); + (void)re_printf("{%11s.%u} %v", comp->icem->name, comp->id, fmt, &ap); va_end(ap); } diff --git a/src/ice/connchk.c b/src/ice/connchk.c index d7c6610..e3c3d87 100644 --- a/src/ice/connchk.c +++ b/src/ice/connchk.c @@ -21,26 +21,16 @@ #include -/** Enable multiple parallel connectivity checks */ -#define ICE_CONNCHECK_MULTIPLE 0 - - static void pace_next(struct icem *icem) { if (icem->state != CHECKLIST_RUNNING) return; -#if 0 - re_printf("\n"); - re_printf("---> Pace next check: checklist=%u validlist=%u" - " triggq=%u\n", - list_count(&icem->checkl), - list_count(&icem->validl), - list_count(&icem->triggl)); -#endif - icem_conncheck_schedule_check(icem); + if (icem->state == CHECKLIST_FAILED) + return; + icem_checklist_update(icem); } @@ -91,6 +81,8 @@ static struct candpair *construct_valid_pair(struct icem *icem, * pair is of type 'host' and the implicit pair is 'srflx' */ + icem_candpair_make_valid(cp); + cp2 = icem_candpair_find(&icem->validl, lcand, rcand); if (cp2) return cp2; @@ -100,7 +92,7 @@ static struct candpair *construct_valid_pair(struct icem *icem, return NULL; icem_candpair_make_valid(cp2); - icem_candpair_failed(cp, EINTR, 0); + /*icem_candpair_failed(cp, EINTR, 0);*/ return cp2; } @@ -114,25 +106,26 @@ static struct candpair *construct_valid_pair(struct icem *icem, static void handle_success(struct icem *icem, struct candpair *cp, - const struct sa *addr) + const struct sa *laddr) { - if (!icem_cand_find(&icem->lcandl, cp->lcand->compid, addr)) { + if (!icem_cand_find(&icem->lcandl, cp->lcand->compid, laddr)) { int err; icecomp_printf(cp->comp, "adding local PRFLX Candidate: %J\n", - addr); + laddr); err = icem_lcand_add(icem, cp->lcand, - CAND_TYPE_PRFLX, addr); + CAND_TYPE_PRFLX, laddr); if (err) { DEBUG_WARNING("failed to add PRFLX: %m\n", err); } } - cp = construct_valid_pair(icem, cp, addr, &cp->rcand->addr); + cp = construct_valid_pair(icem, cp, laddr, &cp->rcand->addr); if (!cp) { - DEBUG_WARNING("no valid pair\n"); + DEBUG_WARNING("{%s.%u} no valid candidate pair for %J\n", + icem->name, cp->comp->id, laddr); return; } @@ -141,8 +134,10 @@ static void handle_success(struct icem *icem, struct candpair *cp, cp->nominated = true; +#if 0 /* stop conncheck now -- conclude */ - icem_conncheck_stop(icem); + icem_conncheck_stop(icem, 0); +#endif } @@ -251,8 +246,6 @@ int icem_conncheck_send(struct candpair *cp, bool use_cand, bool trigged) DEBUG_WARNING("no remote password!\n"); } - cp->usec_sent = ice_get_usec(); - if (cp->ct_conn) { DEBUG_WARNING("send_req: CONNCHECK already Pending!\n"); return EBUSY; @@ -275,7 +268,7 @@ int icem_conncheck_send(struct candpair *cp, bool use_cand, bool trigged) case CAND_TYPE_SRFLX: case CAND_TYPE_PRFLX: cp->ct_conn = mem_deref(cp->ct_conn); - err = stun_request(&cp->ct_conn, icem->stun, icem->proto, + err = stun_request(&cp->ct_conn, ice->stun, icem->proto, cp->comp->sock, &cp->rcand->addr, presz, STUN_METHOD_BINDING, (uint8_t *)icem->rpwd, str_len(icem->rpwd), @@ -284,7 +277,8 @@ int icem_conncheck_send(struct candpair *cp, bool use_cand, bool trigged) STUN_ATTR_USERNAME, username_buf, STUN_ATTR_PRIORITY, &prio_prflx, ctrl_attr, &ice->tiebrk, - STUN_ATTR_USE_CAND, use_cand); + STUN_ATTR_USE_CAND, + use_cand ? &use_cand : 0); break; default: @@ -297,6 +291,20 @@ int icem_conncheck_send(struct candpair *cp, bool use_cand, bool trigged) } +static void abort_ice(struct icem *icem, int err) +{ + icem->state = CHECKLIST_FAILED; + tmr_cancel(&icem->tmr_pace); + + if (icem->chkh) { + icem->chkh(err, icem->ice->lrole == ROLE_CONTROLLING, + icem->arg); + } + + icem->chkh = NULL; +} + + static void do_check(struct candpair *cp) { int err; @@ -304,7 +312,10 @@ static void do_check(struct candpair *cp) err = icem_conncheck_send(cp, false, false); if (err) { icem_candpair_failed(cp, err, 0); - return; + + if (err == ENOMEM) { + abort_ice(cp->icem, err); + } } } @@ -342,20 +353,16 @@ void icem_conncheck_schedule_check(struct icem *icem) /* Terminate the timer for that check list. */ +#if 0 icem->state = CHECKLIST_COMPLETED; +#endif } -static void timeout(void *arg) +static void pace_timeout(void *arg) { struct icem *icem = arg; -#if ICE_CONNCHECK_MULTIPLE - if (icem->state == CHECKLIST_RUNNING) { - tmr_start(&icem->tmr_pace, 100, timeout, icem); - } -#endif - pace_next(icem); } @@ -379,12 +386,12 @@ int icem_conncheck_start(struct icem *icem) icem->state = CHECKLIST_RUNNING; - DEBUG_NOTICE("%s: starting connectivity checks" - " with %u candidate pairs\n", - icem->name, list_count(&icem->checkl)); + icem_printf(icem, "starting connectivity checks" + " with %u candidate pairs\n", + list_count(&icem->checkl)); /* add some delay, to wait for call to be 'established' */ - tmr_start(&icem->tmr_pace, 1000, timeout, icem); + tmr_start(&icem->tmr_pace, 10, pace_timeout, icem); return 0; } @@ -393,28 +400,28 @@ int icem_conncheck_start(struct icem *icem) void icem_conncheck_continue(struct icem *icem) { if (!tmr_isrunning(&icem->tmr_pace)) - tmr_start(&icem->tmr_pace, 1, timeout, icem); + tmr_start(&icem->tmr_pace, 1, pace_timeout, icem); } /** * Stop checklist, cancel all connectivity checks */ -void icem_conncheck_stop(struct icem *icem) +void icem_conncheck_stop(struct icem *icem, int err) { struct le *le; - icem->state = CHECKLIST_COMPLETED; + icem->state = err ? CHECKLIST_FAILED : CHECKLIST_COMPLETED; tmr_cancel(&icem->tmr_pace); for (le = icem->checkl.head; le; le = le->next) { struct candpair *cp = le->data; - icem_candpair_cancel(cp); - - if (cp->state != CANDPAIR_SUCCEEDED) - icem_candpair_failed(cp, EINTR, 0); + if (!icem_candpair_iscompleted(cp)) { + icem_candpair_cancel(cp); + icem_candpair_failed(cp, ECANCELED, 0); + } } icem_checklist_update(icem); diff --git a/src/ice/gather.c b/src/ice/gather.c index 3cceb9a..12c171c 100644 --- a/src/ice/gather.c +++ b/src/ice/gather.c @@ -96,7 +96,7 @@ static int send_binding_request(struct icem *icem, struct icem_comp *comp) if (comp->ct_gath) return EALREADY; - err = stun_request(&comp->ct_gath, icem->stun, icem->proto, + err = stun_request(&comp->ct_gath, icem->ice->stun, icem->proto, comp->sock, &icem->stun_srv, 0, STUN_METHOD_BINDING, NULL, false, 0, @@ -173,8 +173,8 @@ static int cand_gather_relayed(struct icem *icem, struct icem_comp *comp, if (comp->turnc) return EALREADY; - err = turnc_alloc(&comp->turnc, stun_conf(icem->stun), icem->proto, - comp->sock, layer, &icem->stun_srv, + err = turnc_alloc(&comp->turnc, stun_conf(icem->ice->stun), + icem->proto, comp->sock, layer, &icem->stun_srv, username, password, 60, turnc_handler, comp); if (err) @@ -195,6 +195,12 @@ static int start_gathering(struct icem *icem, const struct sa *stun_srv, if (icem->ice->lmode != ICE_MODE_FULL) return EINVAL; + if (list_isempty(&icem->compl)) { + DEBUG_WARNING("gathering: no components for" + " mediastream '%s'\n", icem->name); + return ENOENT; + } + sa_cpy(&icem->stun_srv, stun_srv); /* for each component */ diff --git a/src/ice/ice.c b/src/ice/ice.c index bcd91c0..f4140ea 100644 --- a/src/ice/ice.c +++ b/src/ice/ice.c @@ -50,6 +50,7 @@ static void ice_destructor(void *arg) struct ice *ice = arg; list_flush(&ice->ml); + mem_deref(ice->stun); } @@ -65,6 +66,7 @@ static void ice_destructor(void *arg) int ice_alloc(struct ice **icep, enum ice_mode mode, bool offerer) { struct ice *ice; + int err = 0; if (!icep) return EINVAL; @@ -84,9 +86,24 @@ int ice_alloc(struct ice **icep, enum ice_mode mode, bool offerer) ice_determine_role(ice, offerer); - *icep = ice; + if (ICE_MODE_FULL == ice->lmode) { - return 0; + err = stun_alloc(&ice->stun, NULL, NULL, NULL); + if (err) + goto out; + + /* Update STUN Transport */ + stun_conf(ice->stun)->rto = ice->conf.rto; + stun_conf(ice->stun)->rc = ice->conf.rc; + } + + out: + if (err) + mem_deref(ice); + else + *icep = ice; + + return err; } @@ -166,6 +183,8 @@ int ice_debug(struct re_printf *pf, const struct ice *ice) for (le = ice->ml.head; le; le = le->next) err |= icem_debug(pf, le->data); + err |= stun_debug(pf, ice->stun); + return err; } diff --git a/src/ice/ice.h b/src/ice/ice.h index 68c8937..2957c67 100644 --- a/src/ice/ice.h +++ b/src/ice/ice.h @@ -64,6 +64,7 @@ struct ice { struct list ml; /**< Media list (struct icem) */ uint64_t tiebrk; /**< Tie-break value for roleconflict */ struct ice_conf conf; /**< ICE Configuration */ + struct stun *stun; /**< STUN Transport */ }; /** Defines a media-stream component */ @@ -95,7 +96,6 @@ struct icem { struct list validl; /**< Valid List of cand pairs (sorted) */ bool mismatch; /**< ICE mismatch flag */ struct tmr tmr_pace; /**< Timer for pacing STUN requests */ - struct stun *stun; /**< STUN Transport */ int proto; /**< Transport protocol */ int layer; /**< Protocol layer */ enum checkl_state state; /**< State of the checklist */ @@ -136,8 +136,6 @@ struct candpair { bool nominated; /**< Nominated flag */ enum candpair_state state; /**< Candidate pair state */ uint64_t pprio; /**< Pair priority */ - uint64_t usec_sent; /**< When connectivity request was sent */ - long ertt; /**< Estimated Round-Trip Time in [usec]*/ struct stun_ctrans *ct_conn; /**< STUN Transaction for conncheck */ int err; /**< Saved error code, if failed */ uint16_t scode; /**< Saved STUN code, if failed */ @@ -157,6 +155,8 @@ int icem_rcand_add_prflx(struct cand **rcp, struct icem *icem, uint8_t compid, uint32_t prio, const struct sa *addr); struct cand *icem_cand_find(const struct list *lst, uint8_t compid, const struct sa *addr); +struct cand *icem_lcand_find_checklist(const struct icem *icem, + uint8_t compid); int icem_cands_debug(struct re_printf *pf, const struct list *lst); int icem_cand_print(struct re_printf *pf, const struct cand *c); @@ -183,6 +183,8 @@ struct candpair *icem_candpair_find_st(const struct list *lst, uint8_t compid, enum candpair_state state); struct candpair *icem_candpair_find_compid(const struct list *lst, uint8_t compid); +struct candpair *icem_candpair_find_rcand(struct icem *icem, + const struct cand *rcand); int icem_candpair_debug(struct re_printf *pf, const struct candpair *cp); int icem_candpairs_debug(struct re_printf *pf, const struct list *list); @@ -194,6 +196,7 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, /* ICE media */ void icem_cand_redund_elim(struct icem *icem); +void icem_printf(struct icem *icem, const char *fmt, ...); /* Checklist */ @@ -215,7 +218,6 @@ void icecomp_printf(struct icem_comp *comp, const char *fmt, ...); /* conncheck */ void icem_conncheck_schedule_check(struct icem *icem); void icem_conncheck_continue(struct icem *icem); -void icem_conncheck_stop(struct icem *icem); int icem_conncheck_send(struct candpair *cp, bool use_cand, bool trigged); diff --git a/src/ice/icem.c b/src/ice/icem.c index 2a374fc..20f4c93 100644 --- a/src/ice/icem.c +++ b/src/ice/icem.c @@ -32,7 +32,6 @@ static void icem_destructor(void *data) list_flush(&icem->checkl); list_flush(&icem->lcandl); list_flush(&icem->rcandl); - mem_deref(icem->stun); mem_deref(icem->rufrag); mem_deref(icem->rpwd); } @@ -82,17 +81,6 @@ int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer, icem->chkh = chkh; icem->arg = arg; - if (ICE_MODE_FULL == ice->lmode) { - - err = stun_alloc(&icem->stun, NULL, NULL, NULL); - if (err) - goto out; - - /* Update STUN Transport */ - stun_conf(icem->stun)->rto = ice->conf.rto; - stun_conf(icem->stun)->rc = ice->conf.rc; - } - if (err) goto out; @@ -190,25 +178,27 @@ static void *unique_handler(struct le *le1, struct le *le2) /** Eliminating Redundant Candidates */ void icem_cand_redund_elim(struct icem *icem) { - uint32_t n = ice_list_unique(&icem->lcandl, unique_handler); + uint32_t n; + + n = ice_list_unique(&icem->lcandl, unique_handler); if (n > 0) { - DEBUG_NOTICE("%s: redundant candidates eliminated: %u\n", - icem->name, n); + icem_printf(icem, "redundant candidates eliminated: %u\n", n); } } /** - * Get the Default Candidate + * Get the Default Local Candidate * * @param icem ICE Media object * @param compid Component ID * - * @return Default Candidate address if set, otherwise NULL + * @return Default Local Candidate address if set, otherwise NULL */ const struct sa *icem_cand_default(struct icem *icem, uint8_t compid) { const struct icem_comp *comp = icem_comp_find(icem, compid); + if (!comp || !comp->def_lcand) return NULL; @@ -347,7 +337,6 @@ bool icem_mismatch(const struct icem *icem) */ int icem_debug(struct re_printf *pf, const struct icem *icem) { - struct le *le; int err = 0; if (!icem) @@ -365,18 +354,6 @@ int icem_debug(struct re_printf *pf, const struct icem *icem) err |= re_hprintf(pf, " Valid list: %H", icem_candpairs_debug, &icem->validl); - for (le = icem->compl.head; le; le = le->next) { - - const struct icem_comp *comp = le->data; - - if (comp->cp_sel) { - err |= re_hprintf(pf, " Selected: %H\n", - icem_candpair_debug, comp->cp_sel); - } - } - - err |= stun_debug(pf, icem->stun); - return err; } @@ -392,3 +369,16 @@ struct list *icem_lcandl(const struct icem *icem) { return icem ? (struct list *)&icem->lcandl : NULL; } + + +void icem_printf(struct icem *icem, const char *fmt, ...) +{ + va_list ap; + + if (!icem || !icem->ice->conf.debug) + return; + + va_start(ap, fmt); + (void)re_printf("{%11s. } %v", icem->name, fmt, &ap); + va_end(ap); +} diff --git a/src/ice/icesdp.c b/src/ice/icesdp.c index 6397861..990141a 100644 --- a/src/ice/icesdp.c +++ b/src/ice/icesdp.c @@ -215,7 +215,9 @@ static int cand_decode(struct icem *icem, const char *val) return err; if (ICE_TRANSP_NONE == transp_resolve(&transp)) { - DEBUG_WARNING("transport not supported: %r\n", &transp); + DEBUG_NOTICE("<%s> ignoring candidate with" + " unknown transport=%r (%r:%r)\n", + icem->name, &transp, &cand_type, &addr); return 0; } diff --git a/src/ice/stunsrv.c b/src/ice/stunsrv.c index 19ad809..276a411 100644 --- a/src/ice/stunsrv.c +++ b/src/ice/stunsrv.c @@ -35,11 +35,10 @@ static void triggered_check(struct icem *icem, struct cand *lcand, cp = icem_candpair_find(&icem->checkl, lcand, rcand); if (cp) { - DEBUG_NOTICE("{%s.%u} triggered_check: found CANDPAIR on" - " checklist in state: %s [%H]\n", - icem->name, cp->comp->id, - ice_candpair_state2name(cp->state), - icem_candpair_debug, cp); + icecomp_printf(cp->comp, + "triggered_check: found CandidatePair on" + " checklist in state: %H\n", + icem_candpair_debug, cp); switch (cp->state) { @@ -73,6 +72,8 @@ static void triggered_check(struct icem *icem, struct cand *lcand, } } else { + +#if 0 err = icem_candpair_alloc(&cp, icem, lcand, rcand); if (err) { DEBUG_WARNING("failed to allocate candpair:" @@ -86,108 +87,51 @@ static void triggered_check(struct icem *icem, struct cand *lcand, icem_candpair_set_state(cp, CANDPAIR_WAITING); (void)icem_conncheck_send(cp, false, true); +#endif + } } -static struct candpair *lookup_candpair(struct icem *icem, - const struct cand *rcand) +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 candpair *cp; - - cp = icem_candpair_find(&icem->checkl, NULL, rcand); - if (cp) - return cp; - - cp = icem_candpair_find(&icem->validl, NULL, rcand); - if (cp) - return cp; - - return NULL; -} - - -/** - * Find the highest priority LCAND on the check-list of type HOST/RELAY - */ -static struct cand *lookup_lcand(struct icem *icem, uint8_t compid) -{ - struct le *le; - - for (le = icem->checkl.head; le; le = le->next) { - struct candpair *cp = le->data; - - if (cp->lcand->compid != compid) - continue; - - switch (cp->lcand->type) { - - case CAND_TYPE_HOST: - case CAND_TYPE_RELAY: - return cp->lcand; - - default: - break; - } - } - - return NULL; -} - - -static void 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 = NULL; + struct cand *lcand = NULL, *rcand; struct candpair *cp = NULL; int err; - if (icem->state != CHECKLIST_RUNNING) { - DEBUG_WARNING("{%s.%u} src=%J Checklist is not running (%s)\n", - icem->name, comp->id, src, - ice_checkl_state2name(icem->state)); - return; - } - - /* 7.2.1.3. Learning Peer Reflexive Candidates */ rcand = icem_cand_find(&icem->rcandl, comp->id, src); if (!rcand) { - - icecomp_printf(comp, "Adding PRFLX remote candidate: %J\n", - src); - err = icem_rcand_add_prflx(&rcand, icem, comp->id, prio, src); - if (err) { - DEBUG_WARNING("icem_rcand_add_prflx: %m\n", err); - return; - } + if (err) + return err; } - cp = lookup_candpair(icem, rcand); + cp = icem_candpair_find_rcand(icem, rcand); if (cp) lcand = cp->lcand; - else { - lcand = lookup_lcand(icem, comp->id); - } + else + lcand = icem_lcand_find_checklist(icem, comp->id); if (!lcand) { - DEBUG_WARNING("{%s.%u} no local candidate (checkl=%u)\n", + DEBUG_WARNING("{%s.%u} no local candidate" + " (checklist=%u) (src=%J)\n", icem->name, comp->id, - list_count(&icem->checkl)); + list_count(&icem->checkl), src); + return 0; } - /* 7.2.1.4. Triggered Checks */ if (ICE_MODE_FULL == ice->lmode) triggered_check(icem, lcand, rcand); if (!cp) { - cp = lookup_candpair(icem, rcand); - + 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; } } @@ -204,25 +148,39 @@ static void handle_stun(struct ice *ice, struct icem *icem, /* 7.2.1.5. Updating the Nominated Flag */ if (use_cand) { if (ice->lrole == ROLE_CONTROLLED) { - if (cp && cp->state == CANDPAIR_SUCCEEDED) { - DEBUG_NOTICE("{%s.%u} setting NOMINATED" - " flag on candpair [%H]\n", - icem->name, comp->id, - icem_candpair_debug, cp); + 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 */ - if (cp) { - icem_candpair_make_valid(cp); + icem_candpair_make_valid(cp); - if (ice->conf.nom == ICE_NOMINATION_REGULAR) { - icem_candpair_cancel(cp); - icem_comp_set_selected(comp, cp); - } + if (ice->conf.nom == ICE_NOMINATION_REGULAR) { + icem_candpair_cancel(cp); + icem_comp_set_selected(comp, cp); } } + + return 0; +} + + +static int stunsrv_ereply(struct icem_comp *comp, const struct sa *src, + size_t presz, const struct stun_msg *req, + uint16_t scode, const char *reason) +{ + struct icem *icem = comp->icem; + struct ice *ice = icem->ice; + + return stun_ereply(icem->proto, comp->sock, src, presz, req, + scode, reason, + (uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 1, + STUN_ATTR_SOFTWARE, sw); } @@ -297,7 +255,10 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, if (attr) use_cand = true; - handle_stun(ice, icem, comp, src, prio_prflx, use_cand, presz > 0); + err = handle_stun(ice, icem, comp, src, prio_prflx, + use_cand, presz > 0); + if (err) + goto badmsg; return stun_reply(icem->proto, comp->sock, src, presz, req, (uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 2, @@ -305,20 +266,11 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, STUN_ATTR_SOFTWARE, sw); badmsg: - return stun_ereply(icem->proto, comp->sock, src, presz, req, - 400, "Bad Request", - (uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 1, - STUN_ATTR_SOFTWARE, sw); + return stunsrv_ereply(comp, src, presz, req, 400, "Bad Request"); unauth: - return stun_ereply(icem->proto, comp->sock, src, presz, req, - 401, "Unauthorized", - (uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 1, - STUN_ATTR_SOFTWARE, sw); + return stunsrv_ereply(comp, src, presz, req, 401, "Unauthorized"); conflict: - return stun_ereply(icem->proto, comp->sock, src, presz, req, - 487, "Role Conflict", - (uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 1, - STUN_ATTR_SOFTWARE, sw); + return stunsrv_ereply(comp, src, presz, req, 487, "Role Conflict"); }