ice: add SDP encode/decode of ICE candidate attr

This commit is contained in:
Richard Aas 2015-01-26 08:34:29 +00:00
parent 48ab5ad8db
commit 4d174e571f
4 changed files with 150 additions and 4 deletions

View file

@ -31,6 +31,13 @@ enum ice_cand_type {
ICE_CAND_TYPE_RELAY /**< Relayed candidate */
};
/** ICE TCP protocol type */
enum ice_tcptype {
ICE_TCP_ACTIVE, /**< Active TCP client */
ICE_TCP_PASSIVE, /**< Passive TCP server */
ICE_TCP_SO /**< Simultaneous-open TCP client/server */
};
struct ice;
struct icem;
@ -108,3 +115,20 @@ enum ice_cand_type ice_cand_name2type(const char *name);
uint32_t ice_cand_calc_prio(enum ice_cand_type type, uint16_t local,
uint8_t compid);
/** Defines an SDP candidate attribute */
struct ice_cand_attr {
char foundation[32]; /**< Foundation string */
uint8_t compid; /**< Component ID (1-255) */
int proto; /**< Transport protocol */
uint32_t prio; /**< Priority of this candidate */
struct sa addr; /**< Transport address */
enum ice_cand_type type; /**< Candidate type */
struct sa rel_addr; /**< Related transport address (optional) */
enum ice_tcptype tcptype; /**< TCP candidate type (TCP-only) */
};
int ice_cand_attr_encode(struct re_printf *pf,
const struct ice_cand_attr *cand);
int ice_cand_attr_decode(struct ice_cand_attr *cand, const char *val);

View file

@ -34,7 +34,7 @@ enum candpair_state {
enum ice_transp {
ICE_TRANSP_NONE = -1,
ICE_TRANSP_UDP
ICE_TRANSP_UDP = IPPROTO_UDP
};
/** ICE protocol values */

View file

@ -11,6 +11,7 @@
#include <re_list.h>
#include <re_tmr.h>
#include <re_sa.h>
#include <re_net.h>
#include <re_stun.h>
#include <re_ice.h>
#include "ice.h"
@ -317,3 +318,123 @@ int icem_sdp_decode(struct icem *icem, const char *name, const char *value)
return 0;
}
static const char *ice_tcptype_name(enum ice_tcptype tcptype)
{
switch (tcptype) {
case ICE_TCP_ACTIVE: return "active";
case ICE_TCP_PASSIVE: return "passive";
case ICE_TCP_SO: return "so";
default: return "???";
}
}
static enum ice_tcptype ice_tcptype_resolve(const struct pl *pl)
{
if (0 == pl_strcasecmp(pl, "active")) return ICE_TCP_ACTIVE;
if (0 == pl_strcasecmp(pl, "passive")) return ICE_TCP_PASSIVE;
if (0 == pl_strcasecmp(pl, "so")) return ICE_TCP_SO;
return (enum ice_tcptype)-1;
}
int ice_cand_attr_encode(struct re_printf *pf,
const struct ice_cand_attr *cand)
{
int err = 0;
if (!cand)
return 0;
err |= re_hprintf(pf, "%s %u %s %u %j %u typ %s",
cand->foundation, cand->compid,
net_proto2name(cand->proto), cand->prio,
&cand->addr, sa_port(&cand->addr),
ice_cand_type2name(cand->type));
if (sa_isset(&cand->rel_addr, SA_ADDR))
err |= re_hprintf(pf, " raddr %j", &cand->rel_addr);
if (sa_isset(&cand->rel_addr, SA_PORT))
err |= re_hprintf(pf, " rport %u", sa_port(&cand->rel_addr));
if (cand->proto == IPPROTO_TCP) {
err |= re_hprintf(pf, " tcptype %s",
ice_tcptype_name(cand->tcptype));
}
return err;
}
int ice_cand_attr_decode(struct ice_cand_attr *cand, const char *val)
{
struct pl pl_fnd, pl_compid, pl_transp, pl_prio, pl_addr, pl_port;
struct pl pl_type, pl_raddr, pl_rport, pl_opt = PL_INIT;
size_t len;
char type[8];
int err;
if (!cand || !val)
return EINVAL;
memset(cand, 0, sizeof(*cand));
len = str_len(val);
err = re_regex(val, len,
"[^ ]+ [0-9]+ [a-z]+ [0-9]+ [^ ]+ [0-9]+ typ [a-z]+"
"[^]*",
&pl_fnd, &pl_compid, &pl_transp, &pl_prio,
&pl_addr, &pl_port, &pl_type, &pl_opt);
if (err)
return err;
(void)pl_strcpy(&pl_fnd, cand->foundation, sizeof(cand->foundation));
if (0 == pl_strcasecmp(&pl_transp, "UDP"))
cand->proto = IPPROTO_UDP;
else if (0 == pl_strcasecmp(&pl_transp, "TCP"))
cand->proto = IPPROTO_TCP;
else
cand->proto = 0;
err = sa_set(&cand->addr, &pl_addr, pl_u32(&pl_port));
if (err)
return err;
cand->compid = pl_u32(&pl_compid);
cand->prio = pl_u32(&pl_prio);
(void)pl_strcpy(&pl_type, type, sizeof(type));
cand->type = ice_cand_name2type(type);
/* optional */
if (0 == re_regex(pl_opt.p, pl_opt.l, "raddr [^ ]+ rport [0-9]+",
&pl_raddr, &pl_rport)) {
err = sa_set(&cand->rel_addr, &pl_raddr, pl_u32(&pl_rport));
if (err)
return err;
}
if (cand->proto == IPPROTO_TCP) {
struct pl tcptype;
err = re_regex(pl_opt.p, pl_opt.l, "tcptype [^ ]+",
&tcptype);
if (err)
return err;
cand->tcptype = ice_tcptype_resolve(&tcptype);
}
return 0;
}

View file

@ -36,7 +36,7 @@ enum {
};
static int type_prio(enum ice_cand_type type)
static uint32_t type_prio(enum ice_cand_type type)
{
switch (type) {
@ -52,7 +52,7 @@ static int type_prio(enum ice_cand_type type)
uint32_t ice_cand_calc_prio(enum ice_cand_type type, uint16_t local,
uint8_t compid)
{
return (uint32_t)type_prio(type)<<24 | local<<8 | (256 - compid);
return type_prio(type)<<24 | (uint32_t)local<<8 | (256 - compid);
}
@ -66,8 +66,9 @@ uint32_t ice_cand_calc_prio(enum ice_cand_type type, uint16_t local,
uint64_t ice_calc_pair_prio(uint32_t g, uint32_t d)
{
const uint64_t m = min(g, d);
const uint64_t x = max(g, d);
return (m<<32) + 2*max(g, d) + (g>d?1:0);
return (m<<32) + 2*x + (g>d?1:0);
}