From f35510eb2208644ea8bb7f1af01fdf9286e1aba2 Mon Sep 17 00:00:00 2001 From: Richard Aas Date: Wed, 19 Jan 2011 09:44:20 +0000 Subject: [PATCH] more ICE fixes --- include/re_ice.h | 4 +- mk/symbian/restun.mmp | 4 +- src/ice/cand.c | 32 +++++++++ src/ice/candpair.c | 100 ++++++++++++++++++++------ src/ice/chklist.c | 28 +++++--- src/ice/comp.c | 7 +- src/ice/connchk.c | 132 +++++++++++++++++++++++------------ src/ice/ice.c | 2 +- src/ice/ice.h | 24 +++---- src/ice/icem.c | 4 -- src/ice/mod.mk | 1 - src/ice/stunsrv.c | 159 +++++++++++++++++++++++++----------------- src/ice/triggq.c | 44 ------------ src/ice/util.c | 33 +++++++++ 14 files changed, 367 insertions(+), 207 deletions(-) delete mode 100644 src/ice/triggq.c diff --git a/include/re_ice.h b/include/re_ice.h index fce4436..1bc0508 100644 --- a/include/re_ice.h +++ b/include/re_ice.h @@ -15,8 +15,8 @@ enum ice_compid { }; enum ice_nomination { - NOMINATION_REGULAR = 0, - NOMINATION_AGGRESSIVE + ICE_NOMINATION_REGULAR = 0, + ICE_NOMINATION_AGGRESSIVE }; struct ice; diff --git a/mk/symbian/restun.mmp b/mk/symbian/restun.mmp index d7f685b..c2524de 100644 --- a/mk/symbian/restun.mmp +++ b/mk/symbian/restun.mmp @@ -13,6 +13,9 @@ VENDORID 0 CAPABILITY NetworkServices #endif +MACRO HAVE_SYS_TIME_H +MACRO HAVE_UNISTD_H + SOURCEPATH . SOURCE dll.cpp @@ -28,7 +31,6 @@ SOURCE icem.c SOURCE icesdp.c SOURCE icestr.c SOURCE stunsrv.c -SOURCE triggq.c SOURCE util.c SOURCEPATH ..\..\src\natbd diff --git a/src/ice/cand.c b/src/ice/cand.c index 20c5136..4037dbc 100644 --- a/src/ice/cand.c +++ b/src/ice/cand.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -169,6 +170,37 @@ int icem_rcand_add(struct icem *icem, enum cand_type type, uint8_t compid, } +int icem_rcand_add_prflx(struct cand **rcp, struct icem *icem, uint8_t compid, + uint32_t prio, const struct sa *addr) +{ + struct cand *rcand; + int err; + + if (!icem || !addr) + return EINVAL; + + rcand = mem_zalloc(sizeof(*rcand), cand_destructor); + if (!rcand) + return ENOMEM; + + list_append(&icem->rcandl, &rcand->le, rcand); + + rcand->type = CAND_TYPE_PRFLX; + rcand->compid = compid; + rcand->prio = prio; + rcand->addr = *addr; + + err = re_sdprintf(&rcand->foundation, "%08x", rand_u32()); + + if (err) + mem_deref(rcand); + else if (rcp) + *rcp = rcand; + + return err; +} + + struct cand *icem_cand_find(const struct list *lst, uint8_t compid, const struct sa *addr) { diff --git a/src/ice/candpair.c b/src/ice/candpair.c index 2dcb630..cab4631 100644 --- a/src/ice/candpair.c +++ b/src/ice/candpair.c @@ -26,7 +26,6 @@ static void candpair_destructor(void *data) struct candpair *cp = data; list_unlink(&cp->le); - list_unlink(&cp->le_tq); mem_deref(cp->ct_conn); @@ -35,6 +34,17 @@ static void candpair_destructor(void *data) } +static bool sort_handler(struct le *le1, struct le *le2, void *arg) +{ + const struct candpair *cp1 = le1->data; + const struct candpair *cp2 = le2->data; + + (void)arg; + + return cp1->pprio >= cp2->pprio; +} + + static void candpair_set_pprio(struct candpair *cp) { uint32_t g, d; @@ -52,6 +62,27 @@ static void candpair_set_pprio(struct candpair *cp) } +/** + * Add candidate pair to list, sorted by pair priority (highest is first) + */ +static void list_add_sorted(struct list *list, struct candpair *cp) +{ + struct le *le; + + /* find our slot */ + for (le = list_tail(list); le; le = le->prev) { + struct candpair *cp0 = le->data; + + if (cp->pprio < cp0->pprio) { + list_insert_after(list, le, &cp->le, cp); + return; + } + } + + list_prepend(list, &cp->le, cp); +} + + int icem_candpair_alloc(struct candpair **cpp, struct icem *icem, struct cand *lcand, struct cand *rcand) { @@ -69,18 +100,18 @@ int icem_candpair_alloc(struct candpair **cpp, struct icem *icem, if (!cp) return ENOMEM; - list_append(&icem->checkl, &cp->le, cp); - cp->icem = icem; cp->comp = comp; cp->lcand = mem_ref(lcand); cp->rcand = mem_ref(rcand); cp->state = CANDPAIR_FROZEN; - cp->rtt = -1; + cp->ertt = -1; cp->def = comp->def_lcand == lcand && comp->def_rcand == rcand; candpair_set_pprio(cp); + list_add_sorted(&icem->checkl, cp); + if (cpp) *cpp = cp; @@ -88,14 +119,39 @@ int icem_candpair_alloc(struct candpair **cpp, struct icem *icem, } -static bool sort_handler(struct le *le1, struct le *le2, void *arg) +int icem_candpair_clone(struct candpair **cpp, struct candpair *cp0, + struct cand *lcand, struct cand *rcand) { - const struct candpair *cp1 = le1->data; - const struct candpair *cp2 = le2->data; + struct candpair *cp; - (void)arg; + if (!cp0) + return EINVAL; - return cp1->pprio >= cp2->pprio; + cp = mem_zalloc(sizeof(*cp), candpair_destructor); + if (!cp) + return ENOMEM; + + cp->icem = cp0->icem; + cp->comp = cp0->comp; + cp->lcand = mem_ref(lcand ? lcand : cp0->lcand); + cp->rcand = mem_ref(rcand ? rcand : cp0->rcand); + cp->def = cp0->def; + cp->valid = cp0->valid; + cp->nominated = cp0->nominated; + cp->use_cand = cp0->use_cand; + 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; + + list_add_sorted(&cp0->icem->checkl, cp); + + if (cpp) + *cpp = cp; + + return 0; } @@ -117,7 +173,7 @@ void icem_candpair_prio_order(struct list *lst) void icem_candpair_move(struct candpair *cp, struct list *list) { list_unlink(&cp->le); - list_append(list, &cp->le, cp); + list_add_sorted(list, cp); } @@ -128,8 +184,6 @@ void icem_candpair_cancel(struct candpair *cp) return; cp->ct_conn = mem_deref(cp->ct_conn); - - icem_conncheck_continue(cp->icem); } @@ -142,8 +196,8 @@ void icem_candpair_make_valid(struct candpair *cp) cp->scode = 0; cp->valid = true; - if (cp->tick_sent) - cp->rtt = (int)(tmr_jiffies() - cp->tick_sent); + if (cp->usec_sent) + cp->ertt = (long)(ice_get_usec() - cp->usec_sent); icem_candpair_set_state(cp, CANDPAIR_SUCCEEDED); icem_candpair_move(cp, &cp->icem->validl); @@ -168,12 +222,14 @@ void icem_candpair_set_state(struct candpair *cp, enum candpair_state state) return; if (cp->state != state) { - icecomp_printf(cp->comp, "FSM: %10s ===> %-10s\n", + 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; } - - cp->state = state; } @@ -196,9 +252,6 @@ void icem_candpairs_flush(struct list *lst, enum cand_type type, uint8_t id) if (cp->lcand->type != type) continue; - /* also remove the local candidate */ - mem_deref(cp->lcand); - mem_deref(cp); } } @@ -320,18 +373,19 @@ 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%c} %28H <---> %28H", + err = re_hprintf(pf, "{%u} %10s {%c%c%c%c} %22llu %28H <---> %28H", cp->lcand->compid, ice_candpair_state2name(cp->state), cp->def ? 'D' : ' ', cp->valid ? 'V' : ' ', cp->nominated ? 'N' : ' ', cp->use_cand ? 'U' : ' ', + cp->pprio, icem_cand_print, cp->lcand, icem_cand_print, cp->rcand); - if (cp->rtt != -1) - err |= re_hprintf(pf, " RTT=%dms", cp->rtt); + if (cp->ertt != -1) + err |= re_hprintf(pf, " ERTT = %.2fms", cp->ertt / 1000.0); if (cp->err) err |= re_hprintf(pf, " (%s)", strerror(cp->err)); diff --git a/src/ice/chklist.c b/src/ice/chklist.c index 8239350..115f6a9 100644 --- a/src/ice/chklist.c +++ b/src/ice/chklist.c @@ -21,6 +21,9 @@ #include +/** + * Forming Candidate Pairs + */ static int candpairs_form(struct icem *icem) { struct le *le; @@ -72,7 +75,9 @@ static void *unique_handler(struct le *le1, struct le *le2) } -/** Pruning the Pairs */ +/** + * Pruning the Pairs + */ static void candpair_prune(struct icem *icem) { /* The agent MUST prune the list. @@ -85,12 +90,15 @@ static void candpair_prune(struct icem *icem) uint32_t n = ice_list_unique(&icem->checkl, unique_handler); if (n > 0) { - DEBUG_NOTICE("pruned candidate pairs: %u\n", n); + DEBUG_NOTICE("%s: pruned candidate pairs: %u\n", + icem->name, n); } } -/** Computing States */ +/** + * Computing States + */ static void candpair_set_states(struct icem *icem) { struct le *le, *le2; @@ -205,10 +213,12 @@ static void concluding_ice(struct icem_comp *comp) icem_comp_set_selected(comp, cp); - /* send STUN request with USE_CAND flag via triggered qeueue */ - cp->use_cand = true; - icem_triggq_push(comp->icem, cp); - icem_conncheck_schedule_check(comp->icem); + if (comp->icem->ice->conf.nom == ICE_NOMINATION_REGULAR) { + /* send STUN request with USE_CAND flag via triggered qeueue */ + cp->use_cand = true; + (void)icem_conncheck_send(cp, true); + icem_conncheck_schedule_check(comp->icem); + } comp->concluded = true; } @@ -234,8 +244,8 @@ void icem_checklist_update(struct icem *icem) struct icem_comp *comp = le->data; if (!icem_candpair_find_compid(&icem->validl, comp->id)) { - DEBUG_WARNING("no candidate pair for compid %u\n", - comp->id); + DEBUG_WARNING("%s: no candidate pair for compid %u\n", + icem->name, comp->id); err = ENOENT; break; } diff --git a/src/ice/comp.c b/src/ice/comp.c index 37f0406..3893743 100644 --- a/src/ice/comp.c +++ b/src/ice/comp.c @@ -215,9 +215,14 @@ void icem_comp_set_default_rcand(struct icem_comp *comp, struct cand *rcand) void icem_comp_set_selected(struct icem_comp *comp, struct candpair *cp) { - if (!comp) + if (!comp || !cp) return; + if (cp->state != CANDPAIR_SUCCEEDED) { + DEBUG_WARNING("set_selected: invalid state %s\n", + ice_candpair_state2name(cp->state)); + } + mem_deref(comp->cp_sel); comp->cp_sel = mem_ref(cp); } diff --git a/src/ice/connchk.c b/src/ice/connchk.c index bb31ada..46e1b84 100644 --- a/src/ice/connchk.c +++ b/src/ice/connchk.c @@ -22,11 +22,15 @@ #include -#define ICE_CONNCHECK_MULTIPLE 1 +/** 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" @@ -42,10 +46,15 @@ static void pace_next(struct icem *icem) } -/** Constructing a Valid Pair */ -static void construct_valid_pair(struct icem *icem, struct candpair *cp, - const struct sa *mapped, - const struct sa *dest) +/** + * Constructing a Valid Pair + * + * @return The valid pair + */ +static struct candpair *construct_valid_pair(struct icem *icem, + struct candpair *cp, + const struct sa *mapped, + const struct sa *dest) { struct cand *lcand, *rcand; struct candpair *cp2; @@ -53,13 +62,14 @@ static void construct_valid_pair(struct icem *icem, struct candpair *cp, lcand = icem_cand_find(&icem->lcandl, cp->lcand->compid, mapped); rcand = icem_cand_find(&icem->rcandl, cp->rcand->compid, dest); + if (!lcand) { DEBUG_WARNING("no such local candidate: %J\n", mapped); - return; + return NULL; } if (!rcand) { DEBUG_WARNING("no such remote candidate: %J\n", dest); - return; + return NULL; } /* New candidate? -- implicit success */ @@ -81,22 +91,27 @@ static void construct_valid_pair(struct icem *icem, struct candpair *cp, * This happens for UAs behind NAT where the original * pair is of type 'host' and the implicit pair is 'srflx' */ - icem_candpair_failed(cp, EINTR, 0); - if (icem_candpair_find(&icem->validl, lcand, rcand)) { + cp2 = icem_candpair_find(&icem->validl, lcand, rcand); + if (cp2) { DEBUG_NOTICE("candpair already in VALID list\n"); - return; + return cp2; } - err = icem_candpair_alloc(&cp2, icem, lcand, rcand); + err = icem_candpair_clone(&cp2, cp, lcand, rcand); if (err) - return; + return NULL; icem_candpair_make_valid(cp2); + icem_candpair_failed(cp, EINTR, 0); + + return cp2; } else { /* Add to VALID LIST, the pair that generated the check */ icem_candpair_make_valid(cp); + + return cp; } } @@ -108,9 +123,10 @@ static void handle_success(struct icem *icem, struct candpair *cp, int err; - DEBUG_NOTICE("adding PRFLX Candidate: %J\n", addr); + icecomp_printf(cp->comp, "adding local PRFLX Candidate: %J\n", + addr); - err = icem_lcand_add(icem, cp->lcand->base, + err = icem_lcand_add(icem, cp->lcand, CAND_TYPE_PRFLX, addr); if (err) { DEBUG_WARNING("failed to add PRFLX: %s\n", @@ -118,10 +134,19 @@ static void handle_success(struct icem *icem, struct candpair *cp, } } - construct_valid_pair(icem, cp, addr, &cp->rcand->addr); + cp = construct_valid_pair(icem, cp, addr, &cp->rcand->addr); + if (!cp) { + DEBUG_WARNING("no valid pair\n"); + return; + } - if (icem->ice->lrole == ROLE_CONTROLLING && cp->use_cand) - cp->nominated = true; + icem_candpair_make_valid(cp); + icem_comp_set_selected(cp->comp, cp); + + cp->nominated = true; + + /* stop conncheck now -- conclude */ + icem_conncheck_stop(icem); } @@ -162,10 +187,12 @@ static void stunc_resp_handler(int err, uint16_t scode, const char *reason, case 487: /* Role Conflict */ ice_switch_local_role(icem->ice); icem_candpair_set_state(cp, CANDPAIR_WAITING); - icem_triggq_push(icem, cp); + (void)icem_conncheck_send(cp, true); break; default: + DEBUG_WARNING("%s: STUN Response: %u %s\n", icem->name, + scode, reason); icem_candpair_failed(cp, err, scode); break; } @@ -175,12 +202,11 @@ static void stunc_resp_handler(int err, uint16_t scode, const char *reason, } -static int send_req(struct candpair *cp) +int icem_conncheck_send(struct candpair *cp, bool trigged) { struct cand *lcand = cp->lcand; struct icem *icem = cp->icem; struct ice *ice = icem->ice; - struct icem_comp *comp; char username_buf[64]; size_t presz = 0; int use_cand = 0; @@ -188,10 +214,6 @@ static int send_req(struct candpair *cp) uint16_t ctrl_attr; int err = 0; - comp = icem_comp_find(icem, lcand->compid); - if (!comp) - return ENOENT; - icem_candpair_set_state(cp, CANDPAIR_INPROGRESS); (void)re_snprintf(username_buf, sizeof(username_buf), @@ -205,7 +227,7 @@ static int send_req(struct candpair *cp) case ROLE_CONTROLLING: ctrl_attr = STUN_ATTR_CONTROLLING; - if (cp->use_cand || ice->conf.nom == NOMINATION_AGGRESSIVE) + if (cp->use_cand || ice->conf.nom == ICE_NOMINATION_AGGRESSIVE) use_cand = 1; break; @@ -218,10 +240,11 @@ static int send_req(struct candpair *cp) } #if ICE_TRACE - icecomp_printf(cp->comp, "Tx %H ---> %H (%s) %s\n", - icem_cand_print, cp->lcand, icem_cand_print, cp->rcand, - ice_candpair_state2name(cp->state), - use_cand ? "[USE]" : ""); + icecomp_printf(cp->comp, "Tx %H ---> %H (%s) %s %s\n", + icem_cand_print, cp->lcand, icem_cand_print, cp->rcand, + ice_candpair_state2name(cp->state), + use_cand ? "[USE]" : "", + trigged ? "[Trigged]" : ""); #endif /* A connectivity check MUST utilize the STUN short term credential @@ -232,7 +255,7 @@ static int send_req(struct candpair *cp) DEBUG_WARNING("no remote password!\n"); } - cp->tick_sent = tmr_jiffies(); + cp->usec_sent = ice_get_usec(); if (cp->ct_conn) { DEBUG_WARNING("send_req: CONNCHECK already Pending!\n"); @@ -243,7 +266,7 @@ static int send_req(struct candpair *cp) case CAND_TYPE_RELAY: /* Creating Permissions for Relayed Candidates */ - err = turnc_add_chan(comp->turnc, &cp->rcand->addr, + err = turnc_add_chan(cp->comp->turnc, &cp->rcand->addr, NULL, NULL); if (err) { DEBUG_WARNING("add channel: %s\n", strerror(err)); @@ -254,9 +277,10 @@ static int send_req(struct candpair *cp) case CAND_TYPE_HOST: 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, - comp->sock, &cp->rcand->addr, presz, + cp->comp->sock, &cp->rcand->addr, presz, STUN_METHOD_BINDING, (uint8_t *)icem->rpwd, str_len(icem->rpwd), true, stunc_resp_handler, cp, @@ -267,8 +291,8 @@ static int send_req(struct candpair *cp) STUN_ATTR_USE_CAND, use_cand); break; - case CAND_TYPE_PRFLX: - DEBUG_WARNING("cannot send conncheck from Peer Reflexive\n"); + default: + DEBUG_WARNING("unknown candidate type %d\n", lcand->type); err = EINVAL; break; } @@ -281,7 +305,7 @@ static void do_check(struct candpair *cp) { int err; - err = send_req(cp); + err = icem_conncheck_send(cp, false); if (err) { icem_candpair_failed(cp, err, 0); return; @@ -290,19 +314,12 @@ static void do_check(struct candpair *cp) /** - * 5.8. Scheduling Checks + * Scheduling Checks */ void icem_conncheck_schedule_check(struct icem *icem) { struct candpair *cp; - /* search in triggered check queue first */ - cp = icem_triggq_pop(icem); - if (cp) { - do_check(cp); - return; - } - /* Find the highest priority pair in that check list that is in the Waiting state. */ cp = icem_candpair_find_st(&icem->checkl, 0, CANDPAIR_WAITING); @@ -372,10 +389,11 @@ int icem_conncheck_start(struct icem *icem) DEBUG_NOTICE("starting connectivity checks with %u candidate pairs\n", list_count(&icem->checkl)); #if 0 - re_printf("%H\n", icem_debug, icem); + (void)re_printf("%H\n", icem_debug, icem); #endif - tmr_start(&icem->tmr_pace, 1, timeout, icem); + /* add some delay, to wait for call to be 'established' */ + tmr_start(&icem->tmr_pace, 1000, timeout, icem); return 0; } @@ -386,3 +404,27 @@ void icem_conncheck_continue(struct icem *icem) if (!tmr_isrunning(&icem->tmr_pace)) tmr_start(&icem->tmr_pace, 1, timeout, icem); } + + +/** + * Stop checklist, cancel all connectivity checks + */ +void icem_conncheck_stop(struct icem *icem) +{ + struct le *le; + + icem->state = 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); + } + + icem_checklist_update(icem); +} diff --git a/src/ice/ice.c b/src/ice/ice.c index 5029f5e..3a58ac9 100644 --- a/src/ice/ice.c +++ b/src/ice/ice.c @@ -23,7 +23,7 @@ static const struct ice_conf conf_default = { - NOMINATION_REGULAR, + ICE_NOMINATION_REGULAR, ICE_DEFAULT_RTO_RTP, ICE_DEFAULT_RC, false diff --git a/src/ice/ice.h b/src/ice/ice.h index 755da85..506eb5b 100644 --- a/src/ice/ice.h +++ b/src/ice/ice.h @@ -91,9 +91,8 @@ struct icem { int nstun; /**< Number of pending STUN candidates */ struct list lcandl; /**< List of local candidates */ struct list rcandl; /**< List of remote candidates */ - struct list checkl; /**< Check List of cand pairs */ - struct list validl; /**< Valid List of cand pairs */ - struct list triggl; /**< Triggered check-list */ + struct list checkl; /**< Check List of cand pairs (sorted) */ + 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 */ @@ -128,7 +127,6 @@ struct cand { /** Defines a candidate pair */ struct candpair { struct le le; /**< List element */ - struct le le_tq; /**< Triggered queue element */ struct icem *icem; /**< Pointer to parent ICE media */ struct icem_comp *comp; /**< Pointer to media-stream component */ struct cand *lcand; /**< Local candidate */ @@ -136,11 +134,11 @@ struct candpair { bool def; /**< Default flag */ bool valid; /**< Valid flag */ bool nominated; /**< Nominated flag */ + bool use_cand; /**< Use-candidate flag */ enum candpair_state state; /**< Candidate pair state */ uint64_t pprio; /**< Pair priority */ - uint64_t tick_sent; /**< When connectivity request was sent */ - int rtt; /**< Estimated Round-Trip Time in [ms] */ - bool use_cand; /**< Use-candidate flag */ + 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 */ @@ -156,6 +154,8 @@ int icem_lcand_add(struct icem *icem, struct cand *base, enum cand_type type, int icem_rcand_add(struct icem *icem, enum cand_type type, uint8_t compid, uint32_t prio, const struct sa *addr, const struct sa *rel_addr, const struct pl *foundation); +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); int icem_cands_debug(struct re_printf *pf, const struct list *lst); @@ -165,6 +165,8 @@ int icem_cand_print(struct re_printf *pf, const struct cand *c); /* candpair */ int icem_candpair_alloc(struct candpair **cpp, struct icem *icem, struct cand *lcand, struct cand *rcand); +int icem_candpair_clone(struct candpair **cpp, struct candpair *cp0, + struct cand *lcand, struct cand *rcand); void icem_candpair_prio_order(struct list *lst); void icem_candpair_move(struct candpair *cp, struct list *list); void icem_candpair_cancel(struct candpair *cp); @@ -216,11 +218,8 @@ void icecomp_printf(struct icem_comp *comp, const char *fmt, ...); int icem_conncheck_start(struct icem *icem); void icem_conncheck_schedule_check(struct icem *icem); void icem_conncheck_continue(struct icem *icem); - - -/* triggered check queue */ -void icem_triggq_push(struct icem *icem, struct candpair *cp); -struct candpair *icem_triggq_pop(struct icem *icem); +void icem_conncheck_stop(struct icem *icem); +int icem_conncheck_send(struct candpair *cp, bool trigged); /* icestr */ @@ -239,3 +238,4 @@ uint32_t ice_calc_prio(enum cand_type type, uint16_t local, uint8_t compid); uint64_t ice_calc_pair_prio(uint32_t g, uint32_t d); void ice_switch_local_role(struct ice *ice); uint32_t ice_list_unique(struct list *list, list_unique_h *uh); +uint64_t ice_get_usec(void); diff --git a/src/ice/icem.c b/src/ice/icem.c index 1c07e19..5119fda 100644 --- a/src/ice/icem.c +++ b/src/ice/icem.c @@ -33,7 +33,6 @@ static void icem_destructor(void *data) list_flush(&icem->checkl); list_flush(&icem->lcandl); list_flush(&icem->rcandl); - list_flush(&icem->triggl); mem_deref(icem->stun); mem_deref(icem->rufrag); @@ -62,7 +61,6 @@ int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer, list_init(&icem->rcandl); list_init(&icem->checkl); list_init(&icem->validl); - list_init(&icem->triggl); icem->ice = ice; icem->layer = layer; @@ -280,8 +278,6 @@ int icem_debug(struct re_printf *pf, const struct icem *icem) icem_candpairs_debug, &icem->checkl); err |= re_hprintf(pf, " Valid list: %H", icem_candpairs_debug, &icem->validl); - err |= re_hprintf(pf, " Triggered queue: %H", - icem_candpairs_debug, &icem->triggl); for (le = icem->compl.head; le; le = le->next) { diff --git a/src/ice/mod.mk b/src/ice/mod.mk index e78f0fe..1a6c666 100644 --- a/src/ice/mod.mk +++ b/src/ice/mod.mk @@ -15,5 +15,4 @@ SRCS += ice/icem.c SRCS += ice/icesdp.c SRCS += ice/icestr.c SRCS += ice/stunsrv.c -SRCS += ice/triggq.c SRCS += ice/util.c diff --git a/src/ice/stunsrv.c b/src/ice/stunsrv.c index c344aaa..52cbc20 100644 --- a/src/ice/stunsrv.c +++ b/src/ice/stunsrv.c @@ -25,51 +25,19 @@ static const char *sw = "ice stunsrv v" VERSION " (" ARCH "/" OS ")"; -/** Learning Peer Reflexive Candidates */ -static int learn_peer_reflexive(struct icem_comp *comp, const struct sa *src, - uint32_t prio) -{ - struct icem *icem = comp->icem; - char foundation[8]; - struct pl fnd; - - /* - If the source transport address of the request does not match any - existing remote candidates, it represents a new peer reflexive remote - candidate. This candidate is constructed as follows: - */ - if (icem_cand_find(&icem->rcandl, comp->id, src)) - return 0; - - DEBUG_NOTICE("{%d} Adding Peer-Reflexive remote candidate: %J\n", - comp->id, src); - - /* - The foundation of the candidate is set to an arbitrary value, - different from the foundation for all other remote candidates. If - any subsequent offer/answer exchanges contain this peer reflexive - candidate in the SDP, it will signal the actual foundation for the - candidate. - */ - rand_str(foundation, sizeof(foundation)); - pl_set_str(&fnd, foundation); - - return icem_rcand_add(icem, CAND_TYPE_PRFLX, comp->id, prio, - src, NULL, &fnd); -} - - static void triggered_check(struct icem *icem, struct cand *lcand, struct cand *rcand) { - struct candpair *cp; + struct candpair *cp = NULL; int err; - if (!lcand || !rcand) - return; + if (lcand && rcand) + cp = icem_candpair_find(&icem->checkl, lcand, rcand); - cp = icem_candpair_find(&icem->checkl, lcand, rcand); if (cp) { + DEBUG_NOTICE("triggered_check: found CANDPAIR on checklist" + " in state: %s\n", + ice_candpair_state2name(cp->state)); switch (cp->state) { @@ -91,7 +59,10 @@ static void triggered_check(struct icem *icem, struct cand *lcand, case CANDPAIR_FROZEN: case CANDPAIR_WAITING: - icem_triggq_push(icem, cp); + err = icem_conncheck_send(cp, true); + if (err) { + DEBUG_WARNING("triggered check failed\n"); + } break; case CANDPAIR_SUCCEEDED: @@ -102,7 +73,9 @@ static void triggered_check(struct icem *icem, struct cand *lcand, else { err = icem_candpair_alloc(&cp, icem, lcand, rcand); if (err) { - DEBUG_WARNING("failed to allocate candpair\n"); + DEBUG_WARNING("failed to allocate candpair:" + " lcand=%p rcand=%p (%s)\n", + lcand, rcand, strerror(err)); return; } @@ -110,7 +83,7 @@ static void triggered_check(struct icem *icem, struct cand *lcand, icem_candpair_set_state(cp, CANDPAIR_WAITING); - icem_triggq_push(icem, cp); + (void)icem_conncheck_send(cp, true); } } @@ -128,9 +101,33 @@ static struct candpair *lookup_candpair(struct icem *icem, if (cp) return cp; - cp = icem_candpair_find(&icem->triggl, 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; } @@ -142,16 +139,49 @@ static void handle_stun(struct ice *ice, struct icem *icem, { struct cand *lcand = NULL, *rcand = NULL; struct candpair *cp = NULL; + int err; - rcand = icem_cand_find(&icem->rcandl, comp->id, src); - if (rcand) { - cp = lookup_candpair(icem, rcand); - if (cp) - lcand = cp->lcand; + if (icem->state != CHECKLIST_RUNNING) { + DEBUG_WARNING("Checklist is not running \n"); } + + /* 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: %s\n", + strerror(err)); + return; + } + } + + cp = lookup_candpair(icem, rcand); + if (cp) + lcand = cp->lcand; + else { + lcand = lookup_lcand(icem, comp->id); + } + + if (!lcand) { + DEBUG_WARNING("%s: local candidate not found\n", icem->name); + } + + /* 7.2.1.4. Triggered Checks */ + if (ICE_MODE_FULL == ice->lmode) + triggered_check(icem, lcand, rcand); + if (!cp) { - DEBUG_NOTICE("candidate pair not found: remote=%J\n", src); - /* This can happen for Peer-Reflexive candidates */ + cp = lookup_candpair(icem, rcand); + + if (!cp) { + DEBUG_WARNING("candidate pair not found:" + " source=%J\n", src); + } } #if ICE_TRACE @@ -164,13 +194,6 @@ static void handle_stun(struct ice *ice, struct icem *icem, (void)tunnel; #endif - /* 7.2.1.3. Learning Peer Reflexive Candidates */ - (void)learn_peer_reflexive(comp, src, prio); - - /* 7.2.1.4. Triggered Checks */ - if (ICE_MODE_FULL == ice->lmode) - triggered_check(icem, lcand, rcand); - /* 7.2.1.5. Updating the Nominated Flag */ if (use_cand) { if (ice->lrole == ROLE_CONTROLLED) { @@ -185,12 +208,13 @@ static void handle_stun(struct ice *ice, struct icem *icem, /* Cancel conncheck. Choose Selected Pair */ if (cp) { - icem_candpair_cancel(cp); - icem_comp_set_selected(comp, cp); - } + icem_candpair_make_valid(cp); - /* ICE should complete now .. */ - icem_checklist_update(icem); + if (ice->conf.nom == ICE_NOMINATION_REGULAR) { + icem_candpair_cancel(cp); + icem_comp_set_selected(comp, cp); + } + } } } @@ -227,7 +251,14 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, err = re_regex(attr->v.username, strlen(attr->v.username), "[^:]+:[^]+", &lu, &ru); - if (err || pl_strcmp(&lu, ice->lufrag) || pl_strcmp(&ru, icem->rufrag)) + if (err) { + DEBUG_WARNING("could not parse USERNAME attribute (%s)\n", + attr->v.username); + goto unauth; + } + if (pl_strcmp(&lu, ice->lufrag)) + goto unauth; + if (str_len(icem->rufrag) && pl_strcmp(&ru, icem->rufrag)) goto unauth; attr = stun_msg_attr(req, STUN_ATTR_CONTROLLED); diff --git a/src/ice/triggq.c b/src/ice/triggq.c deleted file mode 100644 index 998522f..0000000 --- a/src/ice/triggq.c +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file triggq.c ICE Triggered Check Queue - * - * Copyright (C) 2010 Creytiv.com - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ice.h" - - -void icem_triggq_push(struct icem *icem, struct candpair *cp) -{ - if (!icem || !cp) - return; - - if (!list_contains(&icem->triggl, &cp->le_tq)) - list_append(&icem->triggl, &cp->le_tq, cp); -} - - -struct candpair *icem_triggq_pop(struct icem *icem) -{ - struct candpair *cp; - - if (!icem) - return NULL; - - cp = list_ledata(icem->triggl.head); - if (!cp) - return NULL; - - list_unlink(&cp->le_tq); - - return cp; -} diff --git a/src/ice/util.c b/src/ice/util.c index 19348c7..a4b3af1 100644 --- a/src/ice/util.c +++ b/src/ice/util.c @@ -4,6 +4,14 @@ * Copyright (C) 2010 Creytiv.com */ #include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef WIN32 +#include +#else +#include +#endif #include #include #include @@ -129,3 +137,28 @@ uint32_t ice_list_unique(struct list *list, list_unique_h *uh) return n; } + + +/** Get time of day in [microseconds] */ +uint64_t ice_get_usec(void) +{ + uint64_t jfs; + +#if defined(WIN32) + FILETIME ft; + ULARGE_INTEGER li; + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + jfs = li.QuadPart/10; +#else + struct timeval now; + + if (0 != gettimeofday(&now, NULL)) + return 0; + + jfs = 1000000UL * now.tv_sec + now.tv_usec; +#endif + + return jfs; +}