From a1f84fe76226f631bdd533f2c253e9fb1638cfd9 Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Fri, 28 Apr 2017 08:13:00 +0200 Subject: [PATCH] Remove ICE Session object (#56) * ice: export enum ice_candpair_state this is related to the work of merging 2 ice-stacks into 1: https://github.com/creytiv/re/wiki/ICE-Stacks-merge * ice: remove ice session (struct ice) * ice: remove list, cleanup * ice: use local role instead of offerer --- include/re_ice.h | 33 +++--- src/ice/candpair.c | 2 +- src/ice/chklist.c | 12 +-- src/ice/comp.c | 4 +- src/ice/connchk.c | 17 ++-- src/ice/gather.c | 6 +- src/ice/ice.c | 244 --------------------------------------------- src/ice/ice.h | 35 ++----- src/ice/icem.c | 151 +++++++++++++++++++++++++--- src/ice/icesdp.c | 42 +++----- src/ice/mod.mk | 1 - src/ice/stunsrv.c | 26 +++-- src/ice/util.c | 15 +-- 13 files changed, 217 insertions(+), 371 deletions(-) diff --git a/include/re_ice.h b/include/re_ice.h index 575adec..aa5b99a 100644 --- a/include/re_ice.h +++ b/include/re_ice.h @@ -45,6 +45,15 @@ enum ice_tcptype { ICE_TCP_SO /**< Simultaneous-open TCP client/server */ }; +/** Candidate pair states */ +enum ice_candpair_state { + ICE_CANDPAIR_FROZEN = 0, /**< Frozen state (default) */ + ICE_CANDPAIR_WAITING, /**< Waiting to become highest on list */ + ICE_CANDPAIR_INPROGRESS, /**< In-Progress state;transac. in progress */ + ICE_CANDPAIR_SUCCEEDED, /**< Succeeded state; successful result */ + ICE_CANDPAIR_FAILED /**< Failed state; check failed */ +}; + struct ice; struct icem; @@ -61,22 +70,15 @@ typedef void (ice_gather_h)(int err, uint16_t scode, const char *reason, 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_conf(struct ice *ice, const struct ice_conf *conf); -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); -int ice_debug(struct re_printf *pf, const struct ice *ice); -struct list *ice_medialist(const struct ice *ice); -const char *ice_ufrag(const struct ice *ice); -const char *ice_pwd(const struct ice *ice); - - /* ICE Media */ -int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer, +int icem_alloc(struct icem **icemp, enum ice_mode mode, + enum ice_role role, int proto, int layer, + uint64_t tiebrk, const char *lufrag, const char *lpwd, ice_gather_h *gh, ice_connchk_h *chkh, void *arg); +struct ice_conf *icem_conf(struct icem *icem); +enum ice_role icem_local_role(const struct icem *icem); +void icem_set_conf(struct icem *icem, const struct ice_conf *conf); +void icem_set_role(struct icem *icem, enum ice_role role); void icem_set_name(struct icem *icem, const char *name); int icem_comp_add(struct icem *icem, unsigned compid, void *sock); int icem_cand_add(struct icem *icem, unsigned compid, uint16_t lprio, @@ -92,6 +94,7 @@ void icem_conncheck_stop(struct icem *icem, int err); int icem_add_chan(struct icem *icem, unsigned compid, const struct sa *raddr); bool icem_mismatch(const struct icem *icem); void icem_update(struct icem *icem); +int ice_sdp_decode(struct icem *ice, const char *name, const char *value); 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); @@ -100,6 +103,7 @@ struct list *icem_checkl(const struct icem *icem); struct list *icem_validl(const struct icem *icem); const struct sa *icem_cand_default(struct icem *icem, unsigned compid); const struct sa *icem_selected_laddr(const struct icem *icem, unsigned compid); +void ice_candpair_set_states(struct icem *icem); struct ice_cand; @@ -119,6 +123,7 @@ extern const char ice_attr_ufrag[]; const char *ice_cand_type2name(enum ice_cand_type type); enum ice_cand_type ice_cand_name2type(const char *name); const char *ice_role2name(enum ice_role role); +const char *ice_candpair_state2name(enum ice_candpair_state st); uint32_t ice_cand_calc_prio(enum ice_cand_type type, uint16_t local, diff --git a/src/ice/candpair.c b/src/ice/candpair.c index e426702..5177992 100644 --- a/src/ice/candpair.c +++ b/src/ice/candpair.c @@ -45,7 +45,7 @@ static void candpair_set_pprio(struct ice_candpair *cp) { uint32_t g, d; - if (ICE_ROLE_CONTROLLING == cp->icem->ice->lrole) { + if (ICE_ROLE_CONTROLLING == cp->icem->lrole) { g = cp->lcand->prio; d = cp->rcand->prio; } diff --git a/src/ice/chklist.c b/src/ice/chklist.c index 8b7c1bc..624f3c4 100644 --- a/src/ice/chklist.c +++ b/src/ice/chklist.c @@ -110,7 +110,7 @@ static void candpair_prune(struct icem *icem) /** * Computing States */ -static void candpair_set_states(struct icem *icem) +void ice_candpair_set_states(struct icem *icem) { struct le *le, *le2; @@ -161,7 +161,7 @@ int icem_checklist_form(struct icem *icem) if (!icem) return EINVAL; - if (ICE_MODE_LITE == icem->ice->lmode) { + if (ICE_MODE_LITE == icem->lmode) { DEBUG_WARNING("%s: Checklist: only valid for full-mode\n", icem->name); return EINVAL; @@ -182,10 +182,6 @@ int icem_checklist_form(struct icem *icem) /* 4. prune the pairs */ candpair_prune(icem); - /* 5. set the pair states -- first media stream only */ - if (icem->ice->ml.head->data == icem) - candpair_set_states(icem); - return err; } @@ -230,7 +226,7 @@ static void concluding_ice(struct icem_comp *comp) icem_comp_set_selected(comp, cp); - if (comp->icem->ice->conf.nom == ICE_NOMINATION_REGULAR) { + if (comp->icem->conf.nom == ICE_NOMINATION_REGULAR) { /* send STUN request with USE_CAND flag via triggered qeueue */ (void)icem_conncheck_send(cp, true, true); @@ -282,7 +278,7 @@ void icem_checklist_update(struct icem *icem) icem->state = err ? ICE_CHECKLIST_FAILED : ICE_CHECKLIST_COMPLETED; if (icem->chkh) { - icem->chkh(err, icem->ice->lrole == ICE_ROLE_CONTROLLING, + icem->chkh(err, icem->lrole == ICE_ROLE_CONTROLLING, icem->arg); } } diff --git a/src/ice/comp.c b/src/ice/comp.c index 4454dd9..94000e9 100644 --- a/src/ice/comp.c +++ b/src/ice/comp.c @@ -52,7 +52,7 @@ static bool helper_recv_handler(struct sa *src, struct mbuf *mb, void *arg) break; default: - (void)stun_ctrans_recv(icem->ice->stun, msg, &ua); + (void)stun_ctrans_recv(icem->stun, msg, &ua); break; } } @@ -266,7 +266,7 @@ void icecomp_printf(struct icem_comp *comp, const char *fmt, ...) { va_list ap; - if (!comp || !comp->icem->ice->conf.debug) + if (!comp || !comp->icem->conf.debug) return; va_start(ap, fmt); diff --git a/src/ice/connchk.c b/src/ice/connchk.c index 3701297..b991884 100644 --- a/src/ice/connchk.c +++ b/src/ice/connchk.c @@ -187,7 +187,7 @@ static void stunc_resp_handler(int err, uint16_t scode, const char *reason, break; case 487: /* Role Conflict */ - ice_switch_local_role(icem->ice); + ice_switch_local_role(icem); (void)icem_conncheck_send(cp, false, true); break; @@ -207,7 +207,6 @@ int icem_conncheck_send(struct ice_candpair *cp, bool use_cand, bool trigged) { struct ice_cand *lcand = cp->lcand; struct icem *icem = cp->icem; - struct ice *ice = icem->ice; char username_buf[64]; size_t presz = 0; uint32_t prio_prflx; @@ -217,17 +216,17 @@ int icem_conncheck_send(struct ice_candpair *cp, bool use_cand, bool trigged) icem_candpair_set_state(cp, ICE_CANDPAIR_INPROGRESS); (void)re_snprintf(username_buf, sizeof(username_buf), - "%s:%s", icem->rufrag, ice->lufrag); + "%s:%s", icem->rufrag, icem->lufrag); /* PRIORITY and USE-CANDIDATE */ prio_prflx = ice_cand_calc_prio(ICE_CAND_TYPE_PRFLX, 0, lcand->compid); - switch (ice->lrole) { + switch (icem->lrole) { case ICE_ROLE_CONTROLLING: ctrl_attr = STUN_ATTR_CONTROLLING; - if (ice->conf.nom == ICE_NOMINATION_AGGRESSIVE) + if (icem->conf.nom == ICE_NOMINATION_AGGRESSIVE) use_cand = true; break; @@ -279,7 +278,7 @@ int icem_conncheck_send(struct ice_candpair *cp, bool use_cand, bool trigged) case ICE_CAND_TYPE_SRFLX: case ICE_CAND_TYPE_PRFLX: cp->ct_conn = mem_deref(cp->ct_conn); - err = stun_request(&cp->ct_conn, ice->stun, icem->proto, + err = stun_request(&cp->ct_conn, icem->stun, icem->proto, cp->comp->sock, &cp->rcand->addr, presz, STUN_METHOD_BINDING, (uint8_t *)icem->rpwd, str_len(icem->rpwd), @@ -287,7 +286,7 @@ int icem_conncheck_send(struct ice_candpair *cp, bool use_cand, bool trigged) 4, STUN_ATTR_USERNAME, username_buf, STUN_ATTR_PRIORITY, &prio_prflx, - ctrl_attr, &ice->tiebrk, + ctrl_attr, &icem->tiebrk, STUN_ATTR_USE_CAND, use_cand ? &use_cand : 0); break; @@ -308,7 +307,7 @@ static void abort_ice(struct icem *icem, int err) tmr_cancel(&icem->tmr_pace); if (icem->chkh) { - icem->chkh(err, icem->ice->lrole == ICE_ROLE_CONTROLLING, + icem->chkh(err, icem->lrole == ICE_ROLE_CONTROLLING, icem->arg); } @@ -391,7 +390,7 @@ int icem_conncheck_start(struct icem *icem) if (!icem) return EINVAL; - if (ICE_MODE_FULL != icem->ice->lmode) + if (ICE_MODE_FULL != icem->lmode) return EINVAL; err = icem_checklist_form(icem); diff --git a/src/ice/gather.c b/src/ice/gather.c index 1705acf..c514ace 100644 --- a/src/ice/gather.c +++ b/src/ice/gather.c @@ -97,7 +97,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->ice->stun, icem->proto, + err = stun_request(&comp->ct_gath, icem->stun, icem->proto, comp->sock, &icem->stun_srv, 0, STUN_METHOD_BINDING, NULL, false, 0, @@ -174,7 +174,7 @@ 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->ice->stun), + err = turnc_alloc(&comp->turnc, stun_conf(icem->stun), icem->proto, comp->sock, layer, &icem->stun_srv, username, password, 60, turnc_handler, comp); @@ -193,7 +193,7 @@ static int start_gathering(struct icem *icem, const struct sa *stun_srv, struct le *le; int err = 0; - if (icem->ice->lmode != ICE_MODE_FULL) + if (icem->lmode != ICE_MODE_FULL) return EINVAL; if (list_isempty(&icem->compl)) { diff --git a/src/ice/ice.c b/src/ice/ice.c index dce82cd..8b13789 100644 --- a/src/ice/ice.c +++ b/src/ice/ice.c @@ -1,245 +1 @@ -/** - * @file ice.c Interactive Connectivity Establishment (ICE) - * - * Copyright (C) 2010 Creytiv.com - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ice.h" - -/* - * ICE Implementation as of RFC 5245 - */ - - -static const struct ice_conf conf_default = { - ICE_NOMINATION_REGULAR, - ICE_DEFAULT_RTO_RTP, - ICE_DEFAULT_RC, - false -}; - - -/** Determining Role */ -static void ice_determine_role(struct ice *ice, bool offerer) -{ - if (!ice) - return; - - if (ice->lmode == ice->rmode) - ice->lrole = offerer - ? ICE_ROLE_CONTROLLING : ICE_ROLE_CONTROLLED; - else if (ice->lmode == ICE_MODE_FULL) - ice->lrole = ICE_ROLE_CONTROLLING; - else - ice->lrole = ICE_ROLE_CONTROLLED; -} - - -static void ice_destructor(void *arg) -{ - struct ice *ice = arg; - - list_flush(&ice->ml); - mem_deref(ice->stun); -} - - -/** - * Allocate a new ICE Session - * - * @param icep Pointer to allocated ICE Session object - * @param mode ICE Mode; Full-mode or Lite-mode - * @param offerer True if we are SDP offerer, otherwise false - * - * @return 0 if success, otherwise errorcode - */ -int ice_alloc(struct ice **icep, enum ice_mode mode, bool offerer) -{ - struct ice *ice; - int err = 0; - - if (!icep) - return EINVAL; - - ice = mem_zalloc(sizeof(*ice), ice_destructor); - if (!ice) - return ENOMEM; - - list_init(&ice->ml); - - ice->conf = conf_default; - ice->lmode = mode; - ice->tiebrk = rand_u64(); - - rand_str(ice->lufrag, sizeof(ice->lufrag)); - rand_str(ice->lpwd, sizeof(ice->lpwd)); - - ice_determine_role(ice, offerer); - - if (ICE_MODE_FULL == ice->lmode) { - - 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; -} - - -/** - * Get the ICE Configuration - * - * @param ice ICE Session - * - * @return ICE Configuration - */ -struct ice_conf *ice_conf(struct ice *ice) -{ - return ice ? &ice->conf : NULL; -} - - -void ice_set_conf(struct ice *ice, const struct ice_conf *conf) -{ - if (!ice || !conf) - return; - - ice->conf = *conf; - - if (ice->stun) { - - /* Update STUN Transport */ - stun_conf(ice->stun)->rto = ice->conf.rto; - stun_conf(ice->stun)->rc = ice->conf.rc; - } -} - - -/** - * Set the offerer flag on the ICE Session - * - * @param ice ICE Session - * @param offerer True if offerer, otherwise false - */ -void ice_set_offerer(struct ice *ice, bool offerer) -{ - if (!ice) - return; - - ice_determine_role(ice, offerer); -} - - -/** - * Start the Connectivity checks on the ICE Session - * - * @param ice ICE Session - * - * @return 0 if success, otherwise errorcode - */ -int ice_conncheck_start(struct ice *ice) -{ - struct le *le; - int err = 0; - - if (!ice) - return EINVAL; - - for (le = ice->ml.head; le; le = le->next) - err |= icem_conncheck_start(le->data); - - return err; -} - - -/** - * Print debug information for the ICE Session - * - * @param pf Print function for debug output - * @param ice ICE Session - * - * @return 0 if success, otherwise errorcode - */ -int ice_debug(struct re_printf *pf, const struct ice *ice) -{ - struct le *le; - int err = 0; - - if (!ice) - return 0; - - err |= re_hprintf(pf, " local_mode=%s, remote_mode=%s", - ice_mode2name(ice->lmode), - ice_mode2name(ice->rmode)); - err |= re_hprintf(pf, ", local_role=%s\n", ice_role2name(ice->lrole)); - err |= re_hprintf(pf, " local_ufrag=\"%s\" local_pwd=\"%s\"\n", - ice->lufrag, ice->lpwd); - - for (le = ice->ml.head; le; le = le->next) - err |= icem_debug(pf, le->data); - - err |= stun_debug(pf, ice->stun); - - return err; -} - - -/** - * Get the list of ICE Media objects (struct icem) for the ICE Session - * - * @param ice ICE Session - * - * @return List of ICE Media objects - */ -struct list *ice_medialist(const struct ice *ice) -{ - return ice ? (struct list *)&ice->ml : NULL; -} - - -/** - * Get the local Username fragment for the ICE Session - * - * @param ice ICE Session - * - * @return Local Username-fragment - */ -const char *ice_ufrag(const struct ice *ice) -{ - return ice ? ice->lufrag : NULL; -} - - -/** - * Get the local password for the ICE Session - * - * @param ice ICE Session - * - * @return Local password - */ -const char *ice_pwd(const struct ice *ice) -{ - return ice ? ice->lpwd : NULL; -} diff --git a/src/ice/ice.h b/src/ice/ice.h index 4bddf44..a6580f4 100644 --- a/src/ice/ice.h +++ b/src/ice/ice.h @@ -17,15 +17,6 @@ enum ice_checkl_state { ICE_CHECKLIST_FAILED }; -/** Candidate pair states */ -enum ice_candpair_state { - ICE_CANDPAIR_FROZEN = 0, /**< Frozen state (default) */ - ICE_CANDPAIR_WAITING, /**< Waiting to become highest on list */ - ICE_CANDPAIR_INPROGRESS, /**< In-Progress state;transac. in progress */ - ICE_CANDPAIR_SUCCEEDED, /**< Succeeded state; successful result */ - ICE_CANDPAIR_FAILED /**< Failed state; check failed */ -}; - enum ice_transp { ICE_TRANSP_NONE = -1, ICE_TRANSP_UDP = IPPROTO_UDP @@ -42,19 +33,6 @@ enum { }; -/** Defines an ICE session */ -struct ice { - enum ice_mode lmode; /**< Local mode */ - enum ice_mode rmode; /**< Remote mode */ - enum ice_role lrole; /**< Local role */ - char lufrag[5]; /**< Local Username fragment */ - 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 */ - struct stun *stun; /**< STUN Transport */ -}; - /** Defines a media-stream component */ struct icem_comp { struct le le; /**< Linked-list element */ @@ -74,20 +52,26 @@ struct icem_comp { /** Defines an ICE media-stream */ struct icem { - struct le le; /**< Linked-list element */ - struct ice *ice; /**< Pointer to parent ICE-session */ + struct ice_conf conf; /**< ICE Configuration */ + struct stun *stun; /**< STUN Transport */ struct sa stun_srv; /**< STUN Server IP address and port */ 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 (sorted) */ struct list validl; /**< Valid List of cand pairs (sorted) */ + uint64_t tiebrk; /**< Tie-break value for roleconflict */ bool mismatch; /**< ICE mismatch flag */ + enum ice_mode lmode; /**< Local mode */ + enum ice_mode rmode; /**< Remote mode */ + enum ice_role lrole; /**< Local role */ struct tmr tmr_pace; /**< Timer for pacing STUN requests */ int proto; /**< Transport protocol */ int layer; /**< Protocol layer */ enum ice_checkl_state state; /**< State of the checklist */ struct list compl; /**< ICE media components */ + char *lufrag; /**< Local Username fragment */ + char *lpwd; /**< Local Password */ char *rufrag; /**< Remote Username fragment */ char *rpwd; /**< Remote Password */ ice_gather_h *gh; /**< Gather handler */ @@ -219,7 +203,6 @@ int icem_conncheck_send(struct ice_candpair *cp, bool use_cand, bool trigged); /* icestr */ const char *ice_mode2name(enum ice_mode mode); -const char *ice_candpair_state2name(enum ice_candpair_state st); const char *ice_checkl_state2name(enum ice_checkl_state cst); @@ -227,5 +210,5 @@ const char *ice_checkl_state2name(enum ice_checkl_state cst); typedef void * (list_unique_h)(struct le *le1, struct le *le2); uint64_t ice_calc_pair_prio(uint32_t g, uint32_t d); -void ice_switch_local_role(struct ice *ice); +void ice_switch_local_role(struct icem *icem); uint32_t ice_list_unique(struct list *list, list_unique_h *uh); diff --git a/src/ice/icem.c b/src/ice/icem.c index ee51294..cc87bad 100644 --- a/src/ice/icem.c +++ b/src/ice/icem.c @@ -21,44 +21,86 @@ #include +/* + * ICE Implementation as of RFC 5245 + */ + + +static const struct ice_conf conf_default = { + ICE_NOMINATION_REGULAR, + ICE_DEFAULT_RTO_RTP, + ICE_DEFAULT_RC, + false +}; + + +/** Determining Role */ +static void ice_determine_role(struct icem *icem, enum ice_role role) +{ + if (!icem) + return; + + if (icem->lmode == icem->rmode) + icem->lrole = role; + else if (icem->lmode == ICE_MODE_FULL) + icem->lrole = ICE_ROLE_CONTROLLING; + else + icem->lrole = ICE_ROLE_CONTROLLED; +} + + static void icem_destructor(void *data) { struct icem *icem = data; - list_unlink(&icem->le); tmr_cancel(&icem->tmr_pace); list_flush(&icem->compl); list_flush(&icem->validl); list_flush(&icem->checkl); list_flush(&icem->lcandl); list_flush(&icem->rcandl); + mem_deref(icem->lufrag); + mem_deref(icem->lpwd); mem_deref(icem->rufrag); mem_deref(icem->rpwd); + mem_deref(icem->stun); } /** * Add a new ICE Media object to the ICE Session * - * @param icemp Pointer to allocated ICE Media object - * @param ice ICE Session - * @param proto Transport protocol - * @param layer Protocol stack layer - * @param gh Gather handler - * @param chkh Connectivity check handler - * @param arg Handler argument + * @param icemp Pointer to allocated ICE Media object + * @param mode ICE mode + * @param role Local ICE role + * @param proto Transport protocol + * @param layer Protocol stack layer + * @param tiebrk Tie-breaker value, must be same for all media streams + * @param lufrag Local username fragment + * @param lpwd Local password + * @param gh Gather handler + * @param chkh Connectivity check handler + * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ -int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer, - ice_gather_h *gh, ice_connchk_h *chkh, void *arg) +int icem_alloc(struct icem **icemp, + enum ice_mode mode, enum ice_role role, + int proto, int layer, + uint64_t tiebrk, const char *lufrag, const char *lpwd, + ice_gather_h *gh, ice_connchk_h *chkh, void *arg) { struct icem *icem; int err = 0; - if (!ice) + if (!icemp || !tiebrk || !lufrag || !lpwd) return EINVAL; + if (str_len(lufrag) < 4 || str_len(lpwd) < 22) { + DEBUG_WARNING("alloc: lufrag/lpwd is too short\n"); + return EINVAL; + } + if (proto != IPPROTO_UDP) return EPROTONOSUPPORT; @@ -66,13 +108,14 @@ int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer, if (!icem) return ENOMEM; + icem->conf = conf_default; + tmr_init(&icem->tmr_pace); list_init(&icem->lcandl); list_init(&icem->rcandl); list_init(&icem->checkl); list_init(&icem->validl); - icem->ice = ice; icem->layer = layer; icem->proto = proto; icem->state = ICE_CHECKLIST_NULL; @@ -84,7 +127,26 @@ int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer, if (err) goto out; - list_append(&ice->ml, &icem->le, icem); + icem->lmode = mode; + icem->tiebrk = tiebrk; + + err |= str_dup(&icem->lufrag, lufrag); + err |= str_dup(&icem->lpwd, lpwd); + if (err) + goto out; + + ice_determine_role(icem, role); + + if (ICE_MODE_FULL == icem->lmode) { + + err = stun_alloc(&icem->stun, NULL, NULL, NULL); + if (err) + goto out; + + /* Update STUN Transport */ + stun_conf(icem->stun)->rto = icem->conf.rto; + stun_conf(icem->stun)->rc = icem->conf.rc; + } out: if (err) @@ -96,6 +158,56 @@ int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer, } +/** + * Get the ICE Configuration + * + * @param icem ICE Media object + * + * @return ICE Configuration + */ +struct ice_conf *icem_conf(struct icem *icem) +{ + return icem ? &icem->conf : NULL; +} + + +enum ice_role icem_local_role(const struct icem *icem) +{ + return icem ? icem->lrole : ICE_ROLE_UNKNOWN; +} + + +void icem_set_conf(struct icem *icem, const struct ice_conf *conf) +{ + if (!icem || !conf) + return; + + icem->conf = *conf; + + if (icem->stun) { + + /* Update STUN Transport */ + stun_conf(icem->stun)->rto = icem->conf.rto; + stun_conf(icem->stun)->rc = icem->conf.rc; + } +} + + +/** + * Set the local role on the ICE Session + * + * @param icem ICE Media object + * @param role Local ICE role + */ +void icem_set_role(struct icem *icem, enum ice_role role) +{ + if (!icem) + return; + + ice_determine_role(icem, role); +} + + /** * Set the name of the ICE Media object, used for debugging * @@ -345,6 +457,13 @@ int icem_debug(struct re_printf *pf, const struct icem *icem) err |= re_hprintf(pf, "----- ICE Media <%s> -----\n", icem->name); + err |= re_hprintf(pf, " local_mode=%s, remote_mode=%s", + ice_mode2name(icem->lmode), + ice_mode2name(icem->rmode)); + err |= re_hprintf(pf, ", local_role=%s\n", ice_role2name(icem->lrole)); + err |= re_hprintf(pf, " local_ufrag=\"%s\" local_pwd=\"%s\"\n", + icem->lufrag, icem->lpwd); + err |= re_hprintf(pf, " Components: (%u)\n", list_count(&icem->compl)); for (le = icem->compl.head; le; le = le->next) { struct icem_comp *comp = le->data; @@ -362,6 +481,8 @@ int icem_debug(struct re_printf *pf, const struct icem *icem) err |= re_hprintf(pf, " Valid list: %H", icem_candpairs_debug, &icem->validl); + err |= stun_debug(pf, icem->stun); + return err; } @@ -430,7 +551,7 @@ int icem_lite_set_default_candidates(struct icem *icem) struct le *le; int err = 0; - if (icem->ice->lmode != ICE_MODE_LITE) + if (icem->lmode != ICE_MODE_LITE) return EINVAL; for (le = icem->compl.head; le; le = le->next) { @@ -448,7 +569,7 @@ void icem_printf(struct icem *icem, const char *fmt, ...) { va_list ap; - if (!icem || !icem->ice->conf.debug) + if (!icem || !icem->conf.debug) return; va_start(ap, fmt); diff --git a/src/ice/icesdp.c b/src/ice/icesdp.c index 84902c2..f05f935 100644 --- a/src/ice/icesdp.c +++ b/src/ice/icesdp.c @@ -96,7 +96,7 @@ bool ice_remotecands_avail(const struct icem *icem) if (!icem) return false; - return icem->ice->lrole == ICE_ROLE_CONTROLLING && + return icem->lrole == ICE_ROLE_CONTROLLING && icem->state == ICE_CHECKLIST_COMPLETED; } @@ -134,23 +134,17 @@ int ice_remotecands_encode(struct re_printf *pf, const struct icem *icem) /* Decode SDP Attributes */ -static int ufrag_decode(struct ice *ice, const char *value) +static int ufrag_decode(struct icem *icem, const char *value) { char *ufrag = NULL; - struct le *le; int err; err = str_dup(&ufrag, value); if (err) return err; - for (le = ice->ml.head; le; le = le->next) { - - struct icem *icem = le->data; - - mem_deref(icem->rufrag); - icem->rufrag = mem_ref(ufrag); - } + mem_deref(icem->rufrag); + icem->rufrag = mem_ref(ufrag); mem_deref(ufrag); @@ -158,23 +152,17 @@ static int ufrag_decode(struct ice *ice, const char *value) } -static int pwd_decode(struct ice *ice, const char *value) +static int pwd_decode(struct icem *icem, const char *value) { char *pwd = NULL; - struct le *le; int err; err = str_dup(&pwd, value); if (err) return err; - for (le = ice->ml.head; le; le = le->next) { - - struct icem *icem = le->data; - - mem_deref(icem->rpwd); - icem->rpwd = mem_ref(pwd); - } + mem_deref(icem->rpwd); + icem->rpwd = mem_ref(pwd); mem_deref(pwd); @@ -265,29 +253,29 @@ static int cand_decode(struct icem *icem, const char *val) /** * Decode SDP session attributes * - * @param ice ICE Session + * @param icem ICE Media object * @param name Name of the SDP attribute * @param value Value of the SDP attribute (optional) * * @return 0 if success, otherwise errorcode */ -int ice_sdp_decode(struct ice *ice, const char *name, const char *value) +int ice_sdp_decode(struct icem *icem, const char *name, const char *value) { - if (!ice) + if (!icem) return EINVAL; if (0 == str_casecmp(name, ice_attr_lite)) { - if (ICE_MODE_LITE == ice->lmode) { + if (ICE_MODE_LITE == icem->lmode) { DEBUG_WARNING("we are lite, peer is also lite!\n"); return EPROTO; } - ice->rmode = ICE_MODE_LITE; - ice->lrole = ICE_ROLE_CONTROLLING; + icem->rmode = ICE_MODE_LITE; + icem->lrole = ICE_ROLE_CONTROLLING; } else if (0 == str_casecmp(name, ice_attr_ufrag)) - return ufrag_decode(ice, value); + return ufrag_decode(icem, value); else if (0 == str_casecmp(name, ice_attr_pwd)) - return pwd_decode(ice, value); + return pwd_decode(icem, value); return 0; } diff --git a/src/ice/mod.mk b/src/ice/mod.mk index 1a6c666..974ef42 100644 --- a/src/ice/mod.mk +++ b/src/ice/mod.mk @@ -10,7 +10,6 @@ SRCS += ice/chklist.c SRCS += ice/comp.c SRCS += ice/connchk.c SRCS += ice/gather.c -SRCS += ice/ice.c SRCS += ice/icem.c SRCS += ice/icesdp.c SRCS += ice/icestr.c diff --git a/src/ice/stunsrv.c b/src/ice/stunsrv.c index 18b534a..5f73f1d 100644 --- a/src/ice/stunsrv.c +++ b/src/ice/stunsrv.c @@ -92,7 +92,7 @@ static void triggered_check(struct icem *icem, struct ice_cand *lcand, /* * 7.2.1. Additional Procedures for Full Implementations */ -static int handle_stun_full(struct ice *ice, struct icem *icem, +static int handle_stun_full(struct icem *icem, struct icem_comp *comp, const struct sa *src, uint32_t prio, bool use_cand, bool tunnel) { @@ -145,7 +145,7 @@ static int handle_stun_full(struct ice *ice, struct icem *icem, /* 7.2.1.5. Updating the Nominated Flag */ if (use_cand) { - if (ice->lrole == ICE_ROLE_CONTROLLED && + if (icem->lrole == ICE_ROLE_CONTROLLED && cp->state == ICE_CANDPAIR_SUCCEEDED) { if (!cp->nominated) { @@ -160,7 +160,7 @@ static int handle_stun_full(struct ice *ice, struct icem *icem, /* Cancel conncheck. Choose Selected Pair */ icem_candpair_make_valid(cp); - if (ice->conf.nom == ICE_NOMINATION_REGULAR) { + if (icem->conf.nom == ICE_NOMINATION_REGULAR) { icem_candpair_cancel(cp); icem_comp_set_selected(comp, cp); } @@ -219,11 +219,10 @@ static int stunsrv_ereply(struct icem_comp *comp, const struct sa *src, 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, + (uint8_t *)icem->lpwd, strlen(icem->lpwd), true, 1, STUN_ATTR_SOFTWARE, sw); } @@ -232,7 +231,6 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, struct stun_msg *req, size_t presz) { struct icem *icem = comp->icem; - struct ice *ice = icem->ice; struct stun_attr *attr; struct pl lu, ru; enum ice_role rrole = ICE_ROLE_UNKNOWN; @@ -246,7 +244,7 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, if (err) return err; - err = stun_msg_chk_mi(req, (uint8_t *)ice->lpwd, strlen(ice->lpwd)); + err = stun_msg_chk_mi(req, (uint8_t *)icem->lpwd, strlen(icem->lpwd)); if (err) { if (err == EBADMSG) goto unauth; @@ -265,7 +263,7 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, attr->v.username); goto unauth; } - if (pl_strcmp(&lu, ice->lufrag)) + if (pl_strcmp(&lu, icem->lufrag)) goto unauth; if (str_isset(icem->rufrag) && pl_strcmp(&ru, icem->rufrag)) goto unauth; @@ -282,9 +280,9 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, tiebrk = attr->v.uint64; } - if (rrole == ice->lrole) { - if (ice->tiebrk >= tiebrk) - ice_switch_local_role(ice); + if (rrole == icem->lrole) { + if (icem->tiebrk >= tiebrk) + ice_switch_local_role(icem); else goto conflict; } @@ -299,8 +297,8 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, if (attr) use_cand = true; - if (ice->lmode == ICE_MODE_FULL) { - err = handle_stun_full(ice, icem, comp, src, prio_prflx, + if (icem->lmode == ICE_MODE_FULL) { + err = handle_stun_full(icem, comp, src, prio_prflx, use_cand, presz > 0); } else { @@ -311,7 +309,7 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src, goto badmsg; return stun_reply(icem->proto, comp->sock, src, presz, req, - (uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 2, + (uint8_t *)icem->lpwd, strlen(icem->lpwd), true, 2, STUN_ATTR_XOR_MAPPED_ADDR, src, STUN_ATTR_SOFTWARE, sw); diff --git a/src/ice/util.c b/src/ice/util.c index 0069bcf..d6376fb 100644 --- a/src/ice/util.c +++ b/src/ice/util.c @@ -72,26 +72,27 @@ uint64_t ice_calc_pair_prio(uint32_t g, uint32_t d) } -void ice_switch_local_role(struct ice *ice) +void ice_switch_local_role(struct icem *icem) { enum ice_role new_role; - struct le *le; - if (ICE_ROLE_CONTROLLING == ice->lrole) + if (ICE_ROLE_CONTROLLING == icem->lrole) new_role = ICE_ROLE_CONTROLLED; else new_role = ICE_ROLE_CONTROLLING; DEBUG_NOTICE("Switch local role from %s to %s\n", - ice_role2name(ice->lrole), ice_role2name(new_role)); + ice_role2name(icem->lrole), ice_role2name(new_role)); - ice->lrole = new_role; + icem->lrole = new_role; +#if 0 /* recompute pair priorities for all media streams */ - for (le = ice->ml.head; le; le = le->next) { - struct icem *icem = le->data; + for (le = icem->le.list->head; le; le = le->next) { + icem = le->data; icem_candpair_prio_order(&icem->checkl); } +#endif }