ice: move gathering to application (#68)

ref: https://github.com/creytiv/re/wiki/ICE-Stacks-merge
This commit is contained in:
Alfred E. Heggestad 2017-07-15 09:12:12 +02:00 committed by Richard Aas
parent b08fc20a28
commit 9263b81ae5
7 changed files with 71 additions and 279 deletions

View file

@ -56,6 +56,7 @@ enum ice_candpair_state {
struct ice;
struct icem;
struct turnc;
/** ICE Configuration */
struct ice_conf {
@ -65,8 +66,6 @@ struct ice_conf {
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);
@ -74,7 +73,7 @@ typedef void (ice_connchk_h)(int err, bool update, 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);
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);
@ -83,9 +82,7 @@ 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,
const char *ifname, const struct sa *addr);
int icem_gather_srflx(struct icem *icem, const struct sa *stun_srv);
int icem_gather_relay(struct icem *icem, const struct sa *stun_srv,
const char *username, const char *password);
int icem_lite_set_default_candidates(struct icem *icem);
bool icem_verify_support(struct icem *icem, unsigned compid,
const struct sa *raddr);
@ -104,12 +101,24 @@ 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);
void icem_cand_redund_elim(struct icem *icem);
int icem_comps_set_default_cand(struct icem *icem);
struct stun *icem_stun(struct icem *icem);
int icem_set_turn_client(struct icem *icem, unsigned compid,
struct turnc *turnc);
struct ice_cand;
bool ice_remotecands_avail(const struct icem *icem);
int ice_cand_encode(struct re_printf *pf, const struct ice_cand *cand);
int ice_remotecands_encode(struct re_printf *pf, const struct icem *icem);
struct ice_cand *icem_cand_find(const struct list *lst, unsigned compid,
const struct sa *addr);
int icem_lcand_add(struct icem *icem, struct ice_cand *base,
enum ice_cand_type type,
const struct sa *addr);
struct ice_cand *icem_lcand_base(struct ice_cand *lcand);
const struct sa *icem_lcand_addr(const struct ice_cand *cand);
extern const char ice_attr_cand[];

View file

@ -258,6 +258,18 @@ struct ice_cand *icem_lcand_find_checklist(const struct icem *icem,
}
struct ice_cand *icem_lcand_base(struct ice_cand *lcand)
{
return lcand ? lcand->base : NULL;
}
const struct sa *icem_lcand_addr(const struct ice_cand *cand)
{
return cand ? &cand->addr : NULL;
}
int icem_cands_debug(struct re_printf *pf, const struct list *lst)
{
struct le *le;

View file

@ -68,7 +68,6 @@ static void destructor(void *arg)
struct icem_comp *comp = arg;
tmr_cancel(&comp->tmr_ka);
mem_deref(comp->ct_gath);
mem_deref(comp->turnc);
mem_deref(comp->cp_sel);
mem_deref(comp->def_lcand);
@ -286,3 +285,21 @@ int icecomp_debug(struct re_printf *pf, const struct icem_comp *comp)
comp->def_rcand ? &comp->def_rcand->addr : NULL,
comp->concluded);
}
int icem_set_turn_client(struct icem *icem, unsigned compid,
struct turnc *turnc)
{
struct icem_comp *comp;
comp = icem_comp_find(icem, compid);
if (!comp)
return ENOENT;
comp->turnc = mem_deref(comp->turnc);
if (turnc)
comp->turnc = mem_ref(turnc);
return 0;
}

View file

@ -1,258 +0,0 @@
/**
* @file gather.c ICE Candidate Gathering
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_fmt.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include <re_list.h>
#include <re_tmr.h>
#include <re_sa.h>
#include <re_stun.h>
#include <re_turn.h>
#include <re_ice.h>
#include "ice.h"
#define DEBUG_MODULE "icegath"
#define DEBUG_LEVEL 5
#include <re_dbg.h>
static void call_gather_handler(int err, struct icem *icem, uint16_t scode,
const char *reason)
{
struct le *le;
/* No more pending requests? */
if (icem->nstun != 0)
return;
if (!icem->gh)
return;
if (err)
goto out;
icem_cand_redund_elim(icem);
for (le = icem->compl.head; le; le = le->next) {
struct icem_comp *comp = le->data;
err |= icem_comp_set_default_cand(comp);
}
out:
icem->gh(err, scode, reason, icem->arg);
icem->gh = NULL;
}
static void stun_resp_handler(int err, uint16_t scode, const char *reason,
const struct stun_msg *msg, void *arg)
{
struct icem_comp *comp = arg;
struct icem *icem = comp->icem;
struct stun_attr *attr;
struct ice_cand *lcand;
--icem->nstun;
if (err || scode > 0) {
DEBUG_WARNING("{%s.%u} STUN Request failed: %m\n",
icem->name, comp->id, err);
goto out;
}
lcand = icem_cand_find(&icem->lcandl, comp->id, NULL);
if (!lcand)
goto out;
attr = stun_msg_attr(msg, STUN_ATTR_XOR_MAPPED_ADDR);
if (!attr)
attr = stun_msg_attr(msg, STUN_ATTR_MAPPED_ADDR);
if (!attr) {
DEBUG_WARNING("no Mapped Address in Response\n");
err = EPROTO;
goto out;
}
err = icem_lcand_add(icem, lcand->base, ICE_CAND_TYPE_SRFLX,
&attr->v.sa);
out:
call_gather_handler(err, icem, scode, reason);
}
/** Gather Server Reflexive address */
static int send_binding_request(struct icem *icem, struct icem_comp *comp)
{
int err;
if (comp->ct_gath)
return EALREADY;
err = stun_request(&comp->ct_gath, icem->stun, icem->proto,
comp->sock, &icem->stun_srv, 0,
STUN_METHOD_BINDING,
NULL, false, 0,
stun_resp_handler, comp, 1,
STUN_ATTR_SOFTWARE, stun_software);
if (err)
return err;
++icem->nstun;
return 0;
}
static void turnc_handler(int err, uint16_t scode, const char *reason,
const struct sa *relay, const struct sa *mapped,
const struct stun_msg *msg, void *arg)
{
struct icem_comp *comp = arg;
struct icem *icem = comp->icem;
struct ice_cand *lcand;
(void)msg;
--icem->nstun;
/* TURN failed, so we destroy the client */
if (err || scode) {
comp->turnc = mem_deref(comp->turnc);
}
if (err) {
DEBUG_WARNING("{%s.%u} TURN Client error: %m\n",
icem->name, comp->id, err);
goto out;
}
if (scode) {
DEBUG_WARNING("{%s.%u} TURN Client error: %u %s\n",
icem->name, comp->id, scode, reason);
err = send_binding_request(icem, comp);
if (err)
goto out;
return;
}
lcand = icem_cand_find(&icem->lcandl, comp->id, NULL);
if (!lcand)
goto out;
if (!sa_cmp(relay, &lcand->base->addr, SA_ALL)) {
err = icem_lcand_add(icem, lcand->base,
ICE_CAND_TYPE_RELAY, relay);
}
if (mapped) {
err |= icem_lcand_add(icem, lcand->base,
ICE_CAND_TYPE_SRFLX, mapped);
}
else {
err |= send_binding_request(icem, comp);
}
out:
call_gather_handler(err, icem, scode, reason);
}
static int cand_gather_relayed(struct icem *icem, struct icem_comp *comp,
const char *username, const char *password)
{
const int layer = icem->layer - 10; /* below ICE stack */
int err;
if (comp->turnc)
return EALREADY;
err = turnc_alloc(&comp->turnc, stun_conf(icem->stun),
icem->proto, comp->sock, layer, &icem->stun_srv,
username, password,
60, turnc_handler, comp);
if (err)
return err;
++icem->nstun;
return 0;
}
static int start_gathering(struct icem *icem, const struct sa *stun_srv,
const char *username, const char *password)
{
struct le *le;
int err = 0;
if (icem->lmode != ICE_MODE_FULL)
return EINVAL;
if (list_isempty(&icem->compl)) {
DEBUG_WARNING("gathering: no components for"
" mediastream '%s'\n", icem->name);
return ENOENT;
}
sa_cpy(&icem->stun_srv, stun_srv);
/* for each component */
for (le = icem->compl.head; le; le = le->next) {
struct icem_comp *comp = le->data;
if (username && password) {
err |= cand_gather_relayed(icem, comp,
username, password);
}
else
err |= send_binding_request(icem, comp);
}
return err;
}
/**
* Gather Server Reflexive candidates using STUN Server
*
* @param icem ICE Media object
* @param stun_srv STUN Server network address
*
* @return 0 if success, otherwise errorcode
*/
int icem_gather_srflx(struct icem *icem, const struct sa *stun_srv)
{
if (!icem || !stun_srv)
return EINVAL;
return start_gathering(icem, stun_srv, NULL, NULL);
}
/**
* Gather Relayed and Server Reflexive candidates using TURN Server
*
* @param icem ICE Media object
* @param stun_srv TURN Server network address
* @param username TURN Server username
* @param password TURN Server password
*
* @return 0 if success, otherwise errorcode
*/
int icem_gather_relay(struct icem *icem, const struct sa *stun_srv,
const char *username, const char *password)
{
if (!icem || !stun_srv || !username || !password)
return EINVAL;
return start_gathering(icem, stun_srv, username, password);
}

View file

@ -46,7 +46,6 @@ struct icem_comp {
unsigned id; /**< Component ID */
bool concluded; /**< Concluded flag */
struct turnc *turnc; /**< TURN Client */
struct stun_ctrans *ct_gath; /**< STUN Transaction for gathering */
struct tmr tmr_ka; /**< Keep-alive timer */
};
@ -55,7 +54,6 @@ struct icem {
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) */
@ -74,7 +72,6 @@ struct icem {
char *lpwd; /**< Local Password */
char *rufrag; /**< Remote Username fragment */
char *rpwd; /**< Remote Password */
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 */
@ -118,17 +115,12 @@ struct ice_candpair {
int icem_lcand_add_base(struct icem *icem, unsigned compid, uint16_t lprio,
const char *ifname, enum ice_transp transp,
const struct sa *addr);
int icem_lcand_add(struct icem *icem, struct ice_cand *base,
enum ice_cand_type type,
const struct sa *addr);
int icem_rcand_add(struct icem *icem, enum ice_cand_type type, unsigned compid,
uint32_t prio, const struct sa *addr,
const struct sa *rel_addr, const struct pl *foundation);
int icem_rcand_add_prflx(struct ice_cand **rcp, struct icem *icem,
unsigned compid, uint32_t prio,
const struct sa *addr);
struct ice_cand *icem_cand_find(const struct list *lst, unsigned compid,
const struct sa *addr);
struct ice_cand *icem_lcand_find_checklist(const struct icem *icem,
unsigned compid);
int icem_cands_debug(struct re_printf *pf, const struct list *lst);
@ -173,7 +165,6 @@ int icem_stund_recv(struct icem_comp *comp, const struct sa *src,
/* ICE media */
void icem_cand_redund_elim(struct icem *icem);
void icem_printf(struct icem *icem, const char *fmt, ...);

View file

@ -78,7 +78,6 @@ static void icem_destructor(void *data)
* @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
*
@ -88,7 +87,7 @@ 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)
ice_connchk_h *chkh, void *arg)
{
struct icem *icem;
int err = 0;
@ -119,8 +118,6 @@ int icem_alloc(struct icem **icemp,
icem->layer = layer;
icem->proto = proto;
icem->state = ICE_CHECKLIST_NULL;
icem->nstun = 0;
icem->gh = gh;
icem->chkh = chkh;
icem->arg = arg;
@ -565,6 +562,31 @@ int icem_lite_set_default_candidates(struct icem *icem)
}
int icem_comps_set_default_cand(struct icem *icem)
{
struct le *le;
int err = 0;
if (!icem)
return EINVAL;
for (le = icem->compl.head; le; le = le->next) {
struct icem_comp *comp = le->data;
err |= icem_comp_set_default_cand(comp);
}
return err;
}
struct stun *icem_stun(struct icem *icem)
{
return icem ? icem->stun : NULL;
}
void icem_printf(struct icem *icem, const char *fmt, ...)
{
va_list ap;

View file

@ -9,7 +9,6 @@ SRCS += ice/candpair.c
SRCS += ice/chklist.c
SRCS += ice/comp.c
SRCS += ice/connchk.c
SRCS += ice/gather.c
SRCS += ice/icem.c
SRCS += ice/icesdp.c
SRCS += ice/icestr.c