ICE fixes
This commit is contained in:
parent
ec3863310f
commit
c069895ffe
11 changed files with 494 additions and 130 deletions
|
@ -14,9 +14,22 @@ enum ice_compid {
|
|||
ICE_COMPID_RTCP = 2
|
||||
};
|
||||
|
||||
enum ice_nomination {
|
||||
NOMINATION_REGULAR = 0,
|
||||
NOMINATION_AGGRESSIVE
|
||||
};
|
||||
|
||||
struct ice;
|
||||
struct icem;
|
||||
|
||||
/** ICE Configuration */
|
||||
struct ice_conf {
|
||||
enum ice_nomination nom; /**< Nomination algorithm */
|
||||
uint32_t rto; /**< STUN Retransmission TimeOut */
|
||||
uint32_t rc; /**< STUN Retransmission Count */
|
||||
bool debug; /**< Enable ICE debugging */
|
||||
};
|
||||
|
||||
typedef void (ice_gather_h)(int err, uint16_t scode, const char *reason,
|
||||
void *arg);
|
||||
typedef void (ice_connchk_h)(int err, bool update, void *arg);
|
||||
|
@ -24,6 +37,7 @@ typedef void (ice_connchk_h)(int err, bool update, void *arg);
|
|||
|
||||
/* ICE Session */
|
||||
int ice_alloc(struct ice **icep, enum ice_mode mode, bool offerer);
|
||||
struct ice_conf *ice_conf(struct ice *ice);
|
||||
void ice_set_offerer(struct ice *ice, bool offerer);
|
||||
int ice_sdp_decode(struct ice *ice, const char *name, const char *value);
|
||||
int ice_conncheck_start(struct ice *ice);
|
||||
|
@ -36,6 +50,7 @@ const char *ice_pwd(const struct ice *ice);
|
|||
/* ICE Media */
|
||||
int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer,
|
||||
ice_gather_h *gh, ice_connchk_h *chkh, void *arg);
|
||||
void icem_set_name(struct icem *icem, const char *name);
|
||||
int icem_comp_add(struct icem *icem, uint8_t compid, void *sock);
|
||||
int icem_cand_add(struct icem *icem, uint8_t compid, uint16_t lprio,
|
||||
const char *ifname, const struct sa *addr);
|
||||
|
@ -46,6 +61,7 @@ bool icem_verify_support(struct icem *icem, uint8_t compid,
|
|||
const struct sa *raddr);
|
||||
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);
|
||||
int icem_sdp_decode(struct icem *icem, const char *name, const char *value);
|
||||
int icem_debug(struct re_printf *pf, const struct icem *icem);
|
||||
struct list *icem_lcandl(const struct icem *icem);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "ice.h"
|
||||
|
||||
|
||||
#define DEBUG_MODULE "candpair"
|
||||
#define DEBUG_MODULE "cndpair"
|
||||
#define DEBUG_LEVEL 5
|
||||
#include <re_dbg.h>
|
||||
|
||||
|
@ -26,6 +26,7 @@ static void candpair_destructor(void *data)
|
|||
struct candpair *cp = data;
|
||||
|
||||
list_unlink(&cp->le);
|
||||
list_unlink(&cp->le_tq);
|
||||
|
||||
mem_deref(cp->ct_conn);
|
||||
|
||||
|
@ -55,10 +56,15 @@ int icem_candpair_alloc(struct candpair **cpp, struct icem *icem,
|
|||
struct cand *lcand, struct cand *rcand)
|
||||
{
|
||||
struct candpair *cp;
|
||||
struct icem_comp *comp;
|
||||
|
||||
if (!icem || !lcand || !rcand)
|
||||
return EINVAL;
|
||||
|
||||
comp = icem_comp_find(icem, lcand->compid);
|
||||
if (!comp)
|
||||
return ENOENT;
|
||||
|
||||
cp = mem_zalloc(sizeof(*cp), candpair_destructor);
|
||||
if (!cp)
|
||||
return ENOMEM;
|
||||
|
@ -66,10 +72,12 @@ int icem_candpair_alloc(struct candpair **cpp, struct icem *icem,
|
|||
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->def = comp->def_lcand == lcand && comp->def_rcand == rcand;
|
||||
|
||||
candpair_set_pprio(cp);
|
||||
|
||||
|
@ -120,6 +128,88 @@ void icem_candpair_cancel(struct candpair *cp)
|
|||
return;
|
||||
|
||||
cp->ct_conn = mem_deref(cp->ct_conn);
|
||||
|
||||
icem_conncheck_continue(cp->icem);
|
||||
}
|
||||
|
||||
|
||||
void icem_candpair_make_valid(struct candpair *cp)
|
||||
{
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
cp->err = 0;
|
||||
cp->scode = 0;
|
||||
cp->valid = true;
|
||||
|
||||
if (cp->tick_sent)
|
||||
cp->rtt = (int)(tmr_jiffies() - cp->tick_sent);
|
||||
|
||||
icem_candpair_set_state(cp, CANDPAIR_SUCCEEDED);
|
||||
icem_candpair_move(cp, &cp->icem->validl);
|
||||
}
|
||||
|
||||
|
||||
void icem_candpair_failed(struct candpair *cp, int err, uint16_t scode)
|
||||
{
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
cp->err = err;
|
||||
cp->scode = scode;
|
||||
|
||||
icem_candpair_set_state(cp, CANDPAIR_FAILED);
|
||||
}
|
||||
|
||||
|
||||
void icem_candpair_set_state(struct candpair *cp, enum candpair_state state)
|
||||
{
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
if (cp->state != state) {
|
||||
icecomp_printf(cp->comp, "FSM: %10s ===> %-10s\n",
|
||||
ice_candpair_state2name(cp->state),
|
||||
ice_candpair_state2name(state));
|
||||
}
|
||||
|
||||
cp->state = state;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete all Candidate-Pairs where the Local candidate is of a given type
|
||||
*/
|
||||
void icem_candpairs_flush(struct list *lst, enum cand_type type, uint8_t id)
|
||||
{
|
||||
struct le *le = list_head(lst);
|
||||
|
||||
while (le) {
|
||||
|
||||
struct candpair *cp = le->data;
|
||||
|
||||
le = le->next;
|
||||
|
||||
if (cp->lcand->compid != id)
|
||||
continue;
|
||||
|
||||
if (cp->lcand->type != type)
|
||||
continue;
|
||||
|
||||
/* also remove the local candidate */
|
||||
mem_deref(cp->lcand);
|
||||
|
||||
mem_deref(cp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool icem_candpair_iscompleted(const struct candpair *cp)
|
||||
{
|
||||
if (!cp)
|
||||
return false;
|
||||
|
||||
return cp->state == CANDPAIR_FAILED || cp->state == CANDPAIR_SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -193,6 +283,25 @@ struct candpair *icem_candpair_find_st(const struct list *lst, uint8_t compid,
|
|||
}
|
||||
|
||||
|
||||
struct candpair *icem_candpair_find_compid(const struct list *lst,
|
||||
uint8_t compid)
|
||||
{
|
||||
struct le *le;
|
||||
|
||||
for (le = list_head(lst); le; le = le->next) {
|
||||
|
||||
struct candpair *cp = le->data;
|
||||
|
||||
if (cp->lcand->compid != compid)
|
||||
continue;
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool icem_candpair_cmp_fnd(const struct candpair *cp1,
|
||||
const struct candpair *cp2)
|
||||
{
|
||||
|
@ -211,7 +320,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%c} %28H --> %28H",
|
||||
err = re_hprintf(pf, "{%u} %10s {%c%c%c%c} %28H <---> %28H",
|
||||
cp->lcand->compid,
|
||||
ice_candpair_state2name(cp->state),
|
||||
cp->def ? 'D' : ' ',
|
||||
|
@ -221,9 +330,14 @@ int icem_candpair_debug(struct re_printf *pf, const struct candpair *cp)
|
|||
icem_cand_print, cp->lcand,
|
||||
icem_cand_print, cp->rcand);
|
||||
|
||||
if (cp->rtt != -1) {
|
||||
if (cp->rtt != -1)
|
||||
err |= re_hprintf(pf, " RTT=%dms", cp->rtt);
|
||||
}
|
||||
|
||||
if (cp->err)
|
||||
err |= re_hprintf(pf, " (%s)", strerror(cp->err));
|
||||
|
||||
if (cp->scode)
|
||||
err |= re_hprintf(pf, " [%u]", cp->scode);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "ice.h"
|
||||
|
||||
|
||||
#define DEBUG_MODULE "checklist"
|
||||
#define DEBUG_MODULE "chklist"
|
||||
#define DEBUG_LEVEL 5
|
||||
#include <re_dbg.h>
|
||||
|
||||
|
@ -118,7 +118,7 @@ static void candpair_set_states(struct icem *icem)
|
|||
cp = cp2;
|
||||
}
|
||||
|
||||
cp->state = CANDPAIR_WAITING;
|
||||
icem_candpair_set_state(cp, CANDPAIR_WAITING);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ int icem_checklist_form(struct icem *icem)
|
|||
/* If all of the pairs in the check list are now either in the Failed or
|
||||
Succeeded state:
|
||||
*/
|
||||
static bool iscompleted(struct icem *icem)
|
||||
static bool iscompleted(const struct icem *icem)
|
||||
{
|
||||
struct le *le;
|
||||
|
||||
|
@ -177,15 +177,8 @@ static bool iscompleted(struct icem *icem)
|
|||
|
||||
const struct candpair *cp = le->data;
|
||||
|
||||
switch (cp->state) {
|
||||
|
||||
case CANDPAIR_FAILED:
|
||||
case CANDPAIR_SUCCEEDED:
|
||||
continue;
|
||||
|
||||
default:
|
||||
if (!icem_candpair_iscompleted(cp))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -221,7 +214,9 @@ static void concluding_ice(struct icem_comp *comp)
|
|||
}
|
||||
|
||||
|
||||
/* 7.1.3.3. Check List and Timer State Updates */
|
||||
/**
|
||||
* Check List and Timer State Updates
|
||||
*/
|
||||
void icem_checklist_update(struct icem *icem)
|
||||
{
|
||||
struct le *le;
|
||||
|
@ -231,15 +226,14 @@ void icem_checklist_update(struct icem *icem)
|
|||
return;
|
||||
|
||||
/*
|
||||
o If there is not a pair in the valid list for each component of the
|
||||
media stream, the state of the check list is set to Failed.
|
||||
*/
|
||||
* If there is not a pair in the valid list for each component of the
|
||||
* media stream, the state of the check list is set to Failed.
|
||||
*/
|
||||
for (le = icem->compl.head; le; le = le->next) {
|
||||
|
||||
struct icem_comp *comp = le->data;
|
||||
|
||||
if (!icem_candpair_find_st(&icem->validl, comp->id,
|
||||
CANDPAIR_SUCCEEDED)) {
|
||||
if (!icem_candpair_find_compid(&icem->validl, comp->id)) {
|
||||
DEBUG_WARNING("no candidate pair for compid %u\n",
|
||||
comp->id);
|
||||
err = ENOENT;
|
||||
|
@ -251,9 +245,7 @@ void icem_checklist_update(struct icem *icem)
|
|||
if (!comp->cp_sel)
|
||||
continue;
|
||||
|
||||
/* remove TURN client if not used */
|
||||
if (comp->cp_sel->lcand->type != CAND_TYPE_RELAY)
|
||||
comp->turnc = mem_deref(comp->turnc);
|
||||
icem_comp_keepalive(comp, true);
|
||||
}
|
||||
|
||||
icem->state = err ? CHECKLIST_FAILED : CHECKLIST_COMPLETED;
|
||||
|
|
138
src/ice/comp.c
138
src/ice/comp.c
|
@ -10,6 +10,7 @@
|
|||
#include <re_mbuf.h>
|
||||
#include <re_list.h>
|
||||
#include <re_tmr.h>
|
||||
#include <re_sys.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_udp.h>
|
||||
#include <re_stun.h>
|
||||
|
@ -18,12 +19,34 @@
|
|||
#include "ice.h"
|
||||
|
||||
|
||||
#define DEBUG_MODULE "comp"
|
||||
#define DEBUG_MODULE "icecomp"
|
||||
#define DEBUG_LEVEL 5
|
||||
#include <re_dbg.h>
|
||||
|
||||
|
||||
enum {COMPID_MIN = 1, COMPID_MAX = 255};
|
||||
enum {DEFAULT_KEEPALIVE = 15};
|
||||
|
||||
|
||||
#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)
|
||||
|
@ -33,40 +56,29 @@ static bool helper_recv_handler(struct sa *src, struct mbuf *mb, void *arg)
|
|||
struct stun_msg *msg = NULL;
|
||||
struct stun_unknown_attr ua;
|
||||
const size_t start = mb->pos;
|
||||
int err;
|
||||
|
||||
#if 0
|
||||
re_printf("{%d} UDP recv_helper: %u bytes from %J\n",
|
||||
comp->id, mbuf_get_left(mb), src);
|
||||
#endif
|
||||
|
||||
err = stun_msg_decode(&msg, mb, &ua);
|
||||
if (err)
|
||||
if (stun_msg_decode(&msg, mb, &ua))
|
||||
return false;
|
||||
|
||||
if (STUN_METHOD_BINDING != stun_msg_method(msg)) {
|
||||
DEBUG_NOTICE("ignore STUN message %s from %J\n",
|
||||
stun_method_name(stun_msg_method(msg)), src);
|
||||
goto out;
|
||||
if (STUN_METHOD_BINDING == stun_msg_method(msg)) {
|
||||
|
||||
switch (stun_msg_class(msg)) {
|
||||
|
||||
case STUN_CLASS_REQUEST:
|
||||
(void)icem_stund_recv(comp, src, msg, start);
|
||||
break;
|
||||
|
||||
default:
|
||||
(void)stun_ctrans_recv(icem->stun, msg, &ua);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (stun_msg_class(msg)) {
|
||||
|
||||
case STUN_CLASS_REQUEST:
|
||||
err = icem_stund_recv(comp, src, msg, start);
|
||||
break;
|
||||
|
||||
case STUN_CLASS_SUCCESS_RESP:
|
||||
case STUN_CLASS_ERROR_RESP:
|
||||
(void)stun_ctrans_recv(icem->stun, msg, &ua);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_WARNING("udp_recv: ignore STUN msg from %J\n", src);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mem_deref(msg);
|
||||
|
||||
return true; /* handled */
|
||||
|
@ -77,10 +89,13 @@ static void destructor(void *data)
|
|||
{
|
||||
struct icem_comp *comp = data;
|
||||
|
||||
tmr_cancel(&comp->tmr_ka);
|
||||
|
||||
mem_deref(comp->ct_gath);
|
||||
mem_deref(comp->turnc);
|
||||
mem_deref(comp->cp_sel);
|
||||
mem_deref(comp->def_cand);
|
||||
mem_deref(comp->def_lcand);
|
||||
mem_deref(comp->def_rcand);
|
||||
mem_deref(comp->uh);
|
||||
mem_deref(comp->sock);
|
||||
}
|
||||
|
@ -141,7 +156,8 @@ int icem_comp_alloc(struct icem_comp **cp, struct icem *icem, int id,
|
|||
comp->sock = mem_ref(sock);
|
||||
comp->icem = icem;
|
||||
|
||||
err = udp_register_helper(&comp->uh, sock, NULL, icem->layer, NULL,
|
||||
err = udp_register_helper(&comp->uh, sock, NULL, icem->layer,
|
||||
NULL, /*helper_send_handler*/
|
||||
helper_recv_handler, comp);
|
||||
if (err)
|
||||
goto out;
|
||||
|
@ -173,13 +189,30 @@ int icem_comp_set_default_cand(struct icem_comp *comp)
|
|||
if (!cand)
|
||||
return ENOENT;
|
||||
|
||||
mem_deref(comp->def_cand);
|
||||
comp->def_cand = mem_ref(cand);
|
||||
mem_deref(comp->def_lcand);
|
||||
comp->def_lcand = mem_ref(cand);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void icem_comp_set_default_rcand(struct icem_comp *comp, struct cand *rcand)
|
||||
{
|
||||
if (!comp)
|
||||
return;
|
||||
|
||||
icecomp_printf(comp, "Set default remote candidate: %s:%J\n",
|
||||
ice_cand_type2name(rcand->type), &rcand->addr);
|
||||
|
||||
mem_deref(comp->def_rcand);
|
||||
comp->def_rcand = mem_ref(rcand);
|
||||
|
||||
if (comp->turnc) {
|
||||
(void)turnc_add_chan(comp->turnc, &rcand->addr, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void icem_comp_set_selected(struct icem_comp *comp, struct candpair *cp)
|
||||
{
|
||||
if (!comp)
|
||||
|
@ -207,3 +240,50 @@ struct icem_comp *icem_comp_find(const struct icem *icem, uint8_t compid)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void timeout(void *arg)
|
||||
{
|
||||
struct icem_comp *comp = arg;
|
||||
struct candpair *cp;
|
||||
|
||||
tmr_start(&comp->tmr_ka, DEFAULT_KEEPALIVE * 1000 + rand_u16() % 1000,
|
||||
timeout, comp);
|
||||
|
||||
/* find selected candidate-pair */
|
||||
cp = comp->cp_sel;
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
(void)stun_indication(comp->icem->proto, comp->sock, &cp->rcand->addr,
|
||||
(cp->lcand->type == CAND_TYPE_RELAY) ? 4 : 0,
|
||||
STUN_METHOD_BINDING, NULL, 0, true, 0);
|
||||
}
|
||||
|
||||
|
||||
void icem_comp_keepalive(struct icem_comp *comp, bool enable)
|
||||
{
|
||||
if (!comp)
|
||||
return;
|
||||
|
||||
if (enable) {
|
||||
tmr_start(&comp->tmr_ka, DEFAULT_KEEPALIVE * 1000,
|
||||
timeout, comp);
|
||||
}
|
||||
else {
|
||||
tmr_cancel(&comp->tmr_ka);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void icecomp_printf(struct icem_comp *comp, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!comp || !comp->icem->ice->conf.debug)
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
(void)re_printf("{%s.%u} %v", comp->icem->name, comp->id, fmt, &ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,24 @@
|
|||
#include <re_dbg.h>
|
||||
|
||||
|
||||
static void pace_next(struct icem *icem);
|
||||
#define ICE_CONNCHECK_MULTIPLE 1
|
||||
|
||||
|
||||
static void pace_next(struct icem *icem)
|
||||
{
|
||||
#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);
|
||||
|
||||
icem_checklist_update(icem);
|
||||
}
|
||||
|
||||
|
||||
/** Constructing a Valid Pair */
|
||||
|
@ -35,7 +52,7 @@ static void construct_valid_pair(struct icem *icem, struct candpair *cp,
|
|||
int err;
|
||||
|
||||
lcand = icem_cand_find(&icem->lcandl, cp->lcand->compid, mapped);
|
||||
rcand = icem_cand_find(&icem->rcandl, cp->lcand->compid, dest);
|
||||
rcand = icem_cand_find(&icem->rcandl, cp->rcand->compid, dest);
|
||||
if (!lcand) {
|
||||
DEBUG_WARNING("no such local candidate: %J\n", mapped);
|
||||
return;
|
||||
|
@ -45,32 +62,41 @@ static void construct_valid_pair(struct icem *icem, struct candpair *cp,
|
|||
return;
|
||||
}
|
||||
|
||||
/* New candidate? */
|
||||
/* New candidate? -- implicit success */
|
||||
if (lcand != cp->lcand || rcand != cp->rcand) {
|
||||
|
||||
/* note: could be optimized */
|
||||
cp->state = CANDPAIR_FAILED;
|
||||
if (lcand != cp->lcand) {
|
||||
icecomp_printf(cp->comp,
|
||||
"New local candidate for mapped %J\n",
|
||||
mapped);
|
||||
}
|
||||
if (rcand != cp->rcand) {
|
||||
icecomp_printf(cp->comp,
|
||||
"New remote candidate for dest %J\n",
|
||||
dest);
|
||||
}
|
||||
|
||||
if (icem_candpair_find(&icem->validl, lcand, rcand))
|
||||
/* The original candidate pair is set to 'Failed' because
|
||||
* the implicitly discovered pair is 'better'.
|
||||
* 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)) {
|
||||
DEBUG_NOTICE("candpair already in VALID list\n");
|
||||
return;
|
||||
}
|
||||
|
||||
err = icem_candpair_alloc(&cp2, icem, lcand, rcand);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
cp2->valid = true;
|
||||
cp2->rtt = (int)(tmr_jiffies() - cp->tick_sent);
|
||||
cp2->state = CANDPAIR_SUCCEEDED;
|
||||
|
||||
/* Add to VALID LIST */
|
||||
icem_candpair_move(cp2, &icem->validl);
|
||||
icem_candpair_make_valid(cp2);
|
||||
}
|
||||
else {
|
||||
/* Add to VALID LIST, the pair that generated the check */
|
||||
cp->valid = true;
|
||||
cp->rtt = (int)(tmr_jiffies() - cp->tick_sent);
|
||||
cp->state = CANDPAIR_SUCCEEDED;
|
||||
icem_candpair_move(cp, &icem->validl);
|
||||
icem_candpair_make_valid(cp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,13 +135,14 @@ static void stunc_resp_handler(int err, uint16_t scode, const char *reason,
|
|||
(void)reason;
|
||||
|
||||
#if ICE_TRACE
|
||||
DEBUG_NOTICE("{id=%u} rx %H <--- %H '%u %s' (%s)\n", cp->lcand->compid,
|
||||
icem_cand_print, cp->lcand, icem_cand_print, cp->rcand,
|
||||
scode, reason, err ? strerror(err) : "");
|
||||
icecomp_printf(cp->comp, "Rx %H <--- %H '%u %s' (%s)\n",
|
||||
icem_cand_print, cp->lcand,
|
||||
icem_cand_print, cp->rcand,
|
||||
scode, reason, err ? strerror(err) : "");
|
||||
#endif
|
||||
|
||||
if (err) {
|
||||
cp->state = CANDPAIR_FAILED;
|
||||
icem_candpair_failed(cp, err, scode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -124,7 +151,8 @@ static void stunc_resp_handler(int err, uint16_t scode, const char *reason,
|
|||
case 0: /* Success case */
|
||||
attr = stun_msg_attr(msg, STUN_ATTR_XOR_MAPPED_ADDR);
|
||||
if (!attr) {
|
||||
cp->state = CANDPAIR_FAILED;
|
||||
DEBUG_WARNING("no XOR-MAPPED-ADDR in response\n");
|
||||
icem_candpair_failed(cp, EBADMSG, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -133,12 +161,12 @@ static void stunc_resp_handler(int err, uint16_t scode, const char *reason,
|
|||
|
||||
case 487: /* Role Conflict */
|
||||
ice_switch_local_role(icem->ice);
|
||||
cp->state = CANDPAIR_WAITING;
|
||||
icem_candpair_set_state(cp, CANDPAIR_WAITING);
|
||||
icem_triggq_push(icem, cp);
|
||||
break;
|
||||
|
||||
default:
|
||||
cp->state = CANDPAIR_FAILED;
|
||||
icem_candpair_failed(cp, err, scode);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -164,12 +192,7 @@ static int send_req(struct candpair *cp)
|
|||
if (!comp)
|
||||
return ENOENT;
|
||||
|
||||
#if ICE_TRACE
|
||||
DEBUG_NOTICE("{id=%u} tx %H ---> %H (%s) %s\n", lcand->compid,
|
||||
icem_cand_print, cp->lcand, icem_cand_print, cp->rcand,
|
||||
ice_candpair_state2name(cp->state),
|
||||
cp->use_cand ? "[USE]" : "");
|
||||
#endif
|
||||
icem_candpair_set_state(cp, CANDPAIR_INPROGRESS);
|
||||
|
||||
(void)re_snprintf(username_buf, sizeof(username_buf),
|
||||
"%s:%s", icem->rufrag, ice->lufrag);
|
||||
|
@ -182,7 +205,7 @@ static int send_req(struct candpair *cp)
|
|||
case ROLE_CONTROLLING:
|
||||
ctrl_attr = STUN_ATTR_CONTROLLING;
|
||||
|
||||
if (cp->use_cand)
|
||||
if (cp->use_cand || ice->conf.nom == NOMINATION_AGGRESSIVE)
|
||||
use_cand = 1;
|
||||
break;
|
||||
|
||||
|
@ -194,6 +217,13 @@ static int send_req(struct candpair *cp)
|
|||
return EINVAL;
|
||||
}
|
||||
|
||||
#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]" : "");
|
||||
#endif
|
||||
|
||||
/* A connectivity check MUST utilize the STUN short term credential
|
||||
mechanism. */
|
||||
|
||||
|
@ -204,6 +234,11 @@ static int send_req(struct candpair *cp)
|
|||
|
||||
cp->tick_sent = tmr_jiffies();
|
||||
|
||||
if (cp->ct_conn) {
|
||||
DEBUG_WARNING("send_req: CONNCHECK already Pending!\n");
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
switch (lcand->type) {
|
||||
|
||||
case CAND_TYPE_RELAY:
|
||||
|
@ -225,7 +260,7 @@ static int send_req(struct candpair *cp)
|
|||
STUN_METHOD_BINDING,
|
||||
(uint8_t *)icem->rpwd, str_len(icem->rpwd),
|
||||
true, stunc_resp_handler, cp,
|
||||
4,
|
||||
3 + use_cand,
|
||||
STUN_ATTR_USERNAME, username_buf,
|
||||
STUN_ATTR_PRIORITY, &prio_prflx,
|
||||
ctrl_attr, &ice->tiebrk,
|
||||
|
@ -248,11 +283,9 @@ static void do_check(struct candpair *cp)
|
|||
|
||||
err = send_req(cp);
|
||||
if (err) {
|
||||
cp->state = CANDPAIR_FAILED;
|
||||
icem_candpair_failed(cp, err, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
cp->state = CANDPAIR_INPROGRESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -304,22 +337,16 @@ static void 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);
|
||||
}
|
||||
|
||||
|
||||
static void pace_next(struct icem *icem)
|
||||
{
|
||||
icem_conncheck_schedule_check(icem);
|
||||
|
||||
icem_checklist_update(icem);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scheduling Checks
|
||||
*/
|
||||
|
@ -342,7 +369,20 @@ int icem_conncheck_start(struct icem *icem)
|
|||
|
||||
icem->state = CHECKLIST_RUNNING;
|
||||
|
||||
DEBUG_NOTICE("starting connectivity checks with %u candidate pairs\n",
|
||||
list_count(&icem->checkl));
|
||||
#if 0
|
||||
re_printf("%H\n", icem_debug, icem);
|
||||
#endif
|
||||
|
||||
tmr_start(&icem->tmr_pace, 1, timeout, icem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void icem_conncheck_continue(struct icem *icem)
|
||||
{
|
||||
if (!tmr_isrunning(&icem->tmr_pace))
|
||||
tmr_start(&icem->tmr_pace, 1, timeout, icem);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ static void stun_resp_handler(int err, uint16_t scode, const char *reason,
|
|||
--icem->nstun;
|
||||
|
||||
if (err || scode > 0) {
|
||||
DEBUG_WARNING("{%u} keepalive failed: %s\n",
|
||||
DEBUG_WARNING("{%u} STUN Request failed: %s\n",
|
||||
comp->id, strerror(err));
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -19,11 +19,17 @@
|
|||
|
||||
/*
|
||||
* ICE Implementation as of RFC 5245
|
||||
*
|
||||
* - only Regular nomination is supported
|
||||
*/
|
||||
|
||||
|
||||
static const struct ice_conf conf_default = {
|
||||
NOMINATION_REGULAR,
|
||||
ICE_DEFAULT_RTO_RTP,
|
||||
ICE_DEFAULT_RC,
|
||||
false
|
||||
};
|
||||
|
||||
|
||||
/** Determining Role */
|
||||
static void ice_determine_role(struct ice *ice, bool offerer)
|
||||
{
|
||||
|
@ -60,6 +66,7 @@ int ice_alloc(struct ice **icep, enum ice_mode mode, bool offerer)
|
|||
|
||||
list_init(&ice->ml);
|
||||
|
||||
ice->conf = conf_default;
|
||||
ice->lmode = mode;
|
||||
ice->tiebrk = rand_u64();
|
||||
|
||||
|
@ -74,6 +81,12 @@ int ice_alloc(struct ice **icep, enum ice_mode mode, bool offerer)
|
|||
}
|
||||
|
||||
|
||||
struct ice_conf *ice_conf(struct ice *ice)
|
||||
{
|
||||
return ice ? &ice->conf : NULL;
|
||||
}
|
||||
|
||||
|
||||
void ice_set_offerer(struct ice *ice, bool offerer)
|
||||
{
|
||||
if (!ice)
|
||||
|
|
|
@ -63,21 +63,24 @@ struct ice {
|
|||
char lpwd[23]; /**< Local Password */
|
||||
struct list ml; /**< Media list (struct icem) */
|
||||
uint64_t tiebrk; /**< Tie-break value for roleconflict */
|
||||
struct ice_conf conf; /**< ICE Configuration */
|
||||
};
|
||||
|
||||
/** Defines a media-stream component */
|
||||
struct icem_comp {
|
||||
struct le le; /**< Linked-list element */
|
||||
struct icem *icem; /**< Parent ICE media */
|
||||
struct cand *def_cand; /**< Default candidate */
|
||||
struct cand *def_lcand; /**< Default local candidate */
|
||||
struct cand *def_rcand; /**< Default remote candidate */
|
||||
struct candpair *cp_sel; /**< Selected candidate-pair */
|
||||
struct udp_helper *uh; /**< UDP helper */
|
||||
void *sock; /**< Transport socket */
|
||||
uint16_t lport; /**< Local port number */
|
||||
uint8_t id; /**< Component ID */
|
||||
bool concluded; /**< Concluded flag */
|
||||
struct turnc *turnc; /**< TURN Client */
|
||||
struct stun_ctrans *ct_gath; /**< STUN Transaction for gathering */
|
||||
struct turnc *turnc; /**< TURN Client */
|
||||
struct stun_ctrans *ct_gath; /**< STUN Transaction for gathering */
|
||||
struct tmr tmr_ka; /**< Keep-alive timer */
|
||||
};
|
||||
|
||||
/** Defines an ICE media-stream */
|
||||
|
@ -103,6 +106,7 @@ struct icem {
|
|||
ice_gather_h *gh; /**< Gather handler */
|
||||
ice_connchk_h *chkh; /**< Connectivity check handler */
|
||||
void *arg; /**< Handler argument */
|
||||
char name[32]; /**< Name of the media stream */
|
||||
};
|
||||
|
||||
/** Defines a candidate */
|
||||
|
@ -124,7 +128,9 @@ 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 */
|
||||
struct cand *rcand; /**< Remote candidate */
|
||||
bool def; /**< Default flag */
|
||||
|
@ -136,6 +142,8 @@ struct candpair {
|
|||
int rtt; /**< Estimated Round-Trip Time in [ms] */
|
||||
bool use_cand; /**< Use-candidate flag */
|
||||
struct stun_ctrans *ct_conn; /**< STUN Transaction for conncheck */
|
||||
int err; /**< Saved error code, if failed */
|
||||
uint16_t scode; /**< Saved STUN code, if failed */
|
||||
};
|
||||
|
||||
|
||||
|
@ -160,6 +168,11 @@ int icem_candpair_alloc(struct candpair **cpp, struct icem *icem,
|
|||
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);
|
||||
void icem_candpair_make_valid(struct candpair *cp);
|
||||
void icem_candpair_failed(struct candpair *cp, int err, uint16_t scode);
|
||||
void icem_candpair_set_state(struct candpair *cp, enum candpair_state state);
|
||||
void icem_candpairs_flush(struct list *lst, enum cand_type type, uint8_t id);
|
||||
bool icem_candpair_iscompleted(const struct candpair *cp);
|
||||
bool icem_candpair_cmp(const struct candpair *cp1, const struct candpair *cp2);
|
||||
bool icem_candpair_cmp_fnd(const struct candpair *cp1,
|
||||
const struct candpair *cp2);
|
||||
|
@ -168,6 +181,8 @@ struct candpair *icem_candpair_find(const struct list *lst,
|
|||
const struct cand *rcand);
|
||||
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);
|
||||
int icem_candpair_debug(struct re_printf *pf, const struct candpair *cp);
|
||||
int icem_candpairs_debug(struct re_printf *pf, const struct list *list);
|
||||
|
||||
|
@ -190,13 +205,17 @@ void icem_checklist_update(struct icem *icem);
|
|||
int icem_comp_alloc(struct icem_comp **cp, struct icem *icem, int id,
|
||||
void *sock);
|
||||
int icem_comp_set_default_cand(struct icem_comp *comp);
|
||||
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);
|
||||
struct icem_comp *icem_comp_find(const struct icem *icem, uint8_t compid);
|
||||
void icem_comp_keepalive(struct icem_comp *comp, bool enable);
|
||||
void icecomp_printf(struct icem_comp *comp, const char *fmt, ...);
|
||||
|
||||
|
||||
/* conncheck */
|
||||
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 */
|
||||
|
|
|
@ -80,8 +80,8 @@ int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer,
|
|||
goto out;
|
||||
|
||||
/* Update STUN Transport */
|
||||
stun_conf(icem->stun)->rto = ICE_DEFAULT_RTO_RTP;
|
||||
stun_conf(icem->stun)->rc = ICE_DEFAULT_RC;
|
||||
stun_conf(icem->stun)->rto = ice->conf.rto;
|
||||
stun_conf(icem->stun)->rc = ice->conf.rc;
|
||||
}
|
||||
|
||||
if (err)
|
||||
|
@ -99,6 +99,15 @@ int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer,
|
|||
}
|
||||
|
||||
|
||||
void icem_set_name(struct icem *icem, const char *name)
|
||||
{
|
||||
if (!icem)
|
||||
return;
|
||||
|
||||
str_ncpy(icem->name, name, sizeof(icem->name));
|
||||
}
|
||||
|
||||
|
||||
int icem_comp_add(struct icem *icem, uint8_t compid, void *sock)
|
||||
{
|
||||
struct icem_comp *comp;
|
||||
|
@ -156,29 +165,42 @@ void icem_cand_redund_elim(struct icem *icem)
|
|||
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_cand)
|
||||
if (!comp || !comp->def_lcand)
|
||||
return NULL;
|
||||
|
||||
return &comp->def_cand->addr;
|
||||
return &comp->def_lcand->addr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifying ICE Support
|
||||
* Verifying ICE Support and set default remote candidate
|
||||
*
|
||||
* @param icem ICE Media
|
||||
* @param compid Component ID
|
||||
* @param raddr Address of default remote candidate
|
||||
*
|
||||
* @return True if ICE is supported, otherwise false
|
||||
*/
|
||||
bool icem_verify_support(struct icem *icem, uint8_t compid,
|
||||
const struct sa *raddr)
|
||||
{
|
||||
struct cand *rcand;
|
||||
bool match;
|
||||
|
||||
if (!icem)
|
||||
return false;
|
||||
|
||||
match = !!icem_cand_find(&icem->rcandl, compid, raddr);
|
||||
rcand = icem_cand_find(&icem->rcandl, compid, raddr);
|
||||
match = rcand != NULL;
|
||||
|
||||
if (!match)
|
||||
icem->mismatch = true;
|
||||
|
||||
if (rcand) {
|
||||
icem_comp_set_default_rcand(icem_comp_find(icem, compid),
|
||||
rcand);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
|
@ -198,6 +220,41 @@ int icem_add_chan(struct icem *icem, uint8_t compid, const struct sa *raddr)
|
|||
}
|
||||
|
||||
|
||||
static void purge_relayed(struct icem *icem, struct icem_comp *comp)
|
||||
{
|
||||
icecomp_printf(comp, "purge local RELAY candidates\n");
|
||||
|
||||
/*
|
||||
* Purge all Candidate-Pairs where the Local candidate
|
||||
* is of type "Relay"
|
||||
*/
|
||||
icem_candpairs_flush(&icem->checkl, CAND_TYPE_RELAY, comp->id);
|
||||
icem_candpairs_flush(&icem->validl, CAND_TYPE_RELAY, comp->id);
|
||||
|
||||
comp->turnc = mem_deref(comp->turnc);
|
||||
}
|
||||
|
||||
|
||||
void icem_update(struct icem *icem)
|
||||
{
|
||||
struct le *le;
|
||||
|
||||
if (!icem)
|
||||
return;
|
||||
|
||||
for (le = icem->compl.head; le; le = le->next) {
|
||||
|
||||
struct icem_comp *comp = le->data;
|
||||
|
||||
/* remove TURN client if not used by local "Selected" */
|
||||
if (comp->cp_sel) {
|
||||
if (comp->cp_sel->lcand->type != CAND_TYPE_RELAY)
|
||||
purge_relayed(icem, comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool icem_mismatch(const struct icem *icem)
|
||||
{
|
||||
return icem ? icem->mismatch : true;
|
||||
|
@ -212,6 +269,8 @@ int icem_debug(struct re_printf *pf, const struct icem *icem)
|
|||
if (!icem)
|
||||
return 0;
|
||||
|
||||
err |= re_hprintf(pf, "----- ICE Media <%s> -----\n", icem->name);
|
||||
|
||||
err |= re_hprintf(pf, " Local Candidates: %H",
|
||||
icem_cands_debug, &icem->lcandl);
|
||||
err |= re_hprintf(pf, " Remote Candidates: %H",
|
||||
|
|
|
@ -41,7 +41,8 @@ static int learn_peer_reflexive(struct icem_comp *comp, const struct sa *src,
|
|||
if (icem_cand_find(&icem->rcandl, comp->id, src))
|
||||
return 0;
|
||||
|
||||
DEBUG_NOTICE("**** Adding Peer-Reflexive candidate: %J\n", src);
|
||||
DEBUG_NOTICE("{%d} Adding Peer-Reflexive remote candidate: %J\n",
|
||||
comp->id, src);
|
||||
|
||||
/*
|
||||
The foundation of the candidate is set to an arbitrary value,
|
||||
|
@ -62,6 +63,7 @@ static void triggered_check(struct icem *icem, struct cand *lcand,
|
|||
struct cand *rcand)
|
||||
{
|
||||
struct candpair *cp;
|
||||
int err;
|
||||
|
||||
if (!lcand || !rcand)
|
||||
return;
|
||||
|
@ -71,12 +73,20 @@ static void triggered_check(struct icem *icem, struct cand *lcand,
|
|||
|
||||
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:
|
||||
cp->state = CANDPAIR_WAITING;
|
||||
icem_candpair_set_state(cp, CANDPAIR_WAITING);
|
||||
/*@fallthrough@*/
|
||||
|
||||
case CANDPAIR_FROZEN:
|
||||
|
@ -85,9 +95,23 @@ static void triggered_check(struct icem *icem, struct cand *lcand,
|
|||
break;
|
||||
|
||||
case CANDPAIR_SUCCEEDED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
err = icem_candpair_alloc(&cp, icem, lcand, rcand);
|
||||
if (err) {
|
||||
DEBUG_WARNING("failed to allocate candpair\n");
|
||||
return;
|
||||
}
|
||||
|
||||
icem_candpair_prio_order(&icem->checkl);
|
||||
|
||||
icem_candpair_set_state(cp, CANDPAIR_WAITING);
|
||||
|
||||
icem_triggq_push(icem, cp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -114,12 +138,10 @@ static struct candpair *lookup_candpair(struct icem *icem,
|
|||
|
||||
static void handle_stun(struct ice *ice, struct icem *icem,
|
||||
struct icem_comp *comp, const struct sa *src,
|
||||
uint32_t prio, bool use_cand)
|
||||
uint32_t prio, bool use_cand, bool tunnel)
|
||||
{
|
||||
struct cand *lcand = NULL;
|
||||
struct cand *rcand = NULL;
|
||||
struct cand *lcand = NULL, *rcand = NULL;
|
||||
struct candpair *cp = NULL;
|
||||
int err;
|
||||
|
||||
rcand = icem_cand_find(&icem->rcandl, comp->id, src);
|
||||
if (rcand) {
|
||||
|
@ -133,15 +155,30 @@ static void handle_stun(struct ice *ice, struct icem *icem,
|
|||
}
|
||||
|
||||
#if ICE_TRACE
|
||||
DEBUG_NOTICE("{id=%u} Binding Request from %J (candpair=%s)\n",
|
||||
comp->id, src,
|
||||
cp ? ice_candpair_state2name(cp->state) : "n/a");
|
||||
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.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) {
|
||||
if (cp && cp->state == CANDPAIR_SUCCEEDED) {
|
||||
DEBUG_NOTICE("setting NOMINATED flag\n");
|
||||
DEBUG_NOTICE("{id=%d} setting NOMINATED"
|
||||
" flag on candpair [%H]\n",
|
||||
comp->id,
|
||||
icem_candpair_debug, cp);
|
||||
cp->nominated = true;
|
||||
}
|
||||
}
|
||||
|
@ -151,15 +188,10 @@ static void handle_stun(struct ice *ice, struct icem *icem,
|
|||
icem_candpair_cancel(cp);
|
||||
icem_comp_set_selected(comp, cp);
|
||||
}
|
||||
|
||||
/* ICE should complete now .. */
|
||||
icem_checklist_update(icem);
|
||||
}
|
||||
|
||||
/* Send TRIGGERED CHECK to peer if mode=full */
|
||||
if (ICE_MODE_FULL == ice->lmode)
|
||||
triggered_check(icem, lcand, rcand);
|
||||
|
||||
err = learn_peer_reflexive(comp, src, prio);
|
||||
|
||||
/* 7.2.1.5. Updating the Nominated Flag */
|
||||
}
|
||||
|
||||
|
||||
|
@ -227,7 +259,7 @@ 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);
|
||||
handle_stun(ice, icem, comp, src, prio_prflx, use_cand, presz > 0);
|
||||
|
||||
return stun_reply(icem->proto, comp->sock, src, presz, req,
|
||||
(uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 2,
|
||||
|
|
|
@ -22,8 +22,8 @@ void icem_triggq_push(struct icem *icem, struct candpair *cp)
|
|||
if (!icem || !cp)
|
||||
return;
|
||||
|
||||
if (!list_contains(&icem->triggl, &cp->le))
|
||||
icem_candpair_move(cp, &icem->triggl);
|
||||
if (!list_contains(&icem->triggl, &cp->le_tq))
|
||||
list_append(&icem->triggl, &cp->le_tq, cp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,8 +38,7 @@ struct candpair *icem_triggq_pop(struct icem *icem)
|
|||
if (!cp)
|
||||
return NULL;
|
||||
|
||||
/* Move candidate pair back to Check-List */
|
||||
icem_candpair_move(cp, &icem->checkl);
|
||||
list_unlink(&cp->le_tq);
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue