From 4d174e571f5e68c01bc2252cb9bf8e22ed0f71b7 Mon Sep 17 00:00:00 2001 From: Richard Aas Date: Mon, 26 Jan 2015 08:34:29 +0000 Subject: [PATCH] ice: add SDP encode/decode of ICE candidate attr --- include/re_ice.h | 24 ++++++++++ src/ice/ice.h | 2 +- src/ice/icesdp.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++ src/ice/util.c | 7 +-- 4 files changed, 150 insertions(+), 4 deletions(-) diff --git a/include/re_ice.h b/include/re_ice.h index 58a7697..209d833 100644 --- a/include/re_ice.h +++ b/include/re_ice.h @@ -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); diff --git a/src/ice/ice.h b/src/ice/ice.h index 536e27f..294d1de 100644 --- a/src/ice/ice.h +++ b/src/ice/ice.h @@ -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 */ diff --git a/src/ice/icesdp.c b/src/ice/icesdp.c index 9f12ba3..64e5ac2 100644 --- a/src/ice/icesdp.c +++ b/src/ice/icesdp.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #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; +} diff --git a/src/ice/util.c b/src/ice/util.c index 0ede026..6ecc167 100644 --- a/src/ice/util.c +++ b/src/ice/util.c @@ -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); }