ice: move gathering to application (#68)
ref: https://github.com/creytiv/re/wiki/ICE-Stacks-merge
This commit is contained in:
parent
b08fc20a28
commit
9263b81ae5
7 changed files with 71 additions and 279 deletions
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
258
src/ice/gather.c
258
src/ice/gather.c
|
@ -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);
|
||||
}
|
|
@ -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, ...);
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue