|
|
|
@ -5,6 +5,7 @@ |
|
|
|
#include <netinet/ip.h> |
|
|
|
#include <arpa/inet.h> |
|
|
|
#include <math.h> |
|
|
|
#include <stdbool.h> |
|
|
|
|
|
|
|
#include "compat.h" |
|
|
|
#include "call.h" |
|
|
|
@ -621,7 +622,7 @@ err: |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int parse_attribute_candidate(struct sdp_attribute *output) { |
|
|
|
static int parse_attribute_candidate(struct sdp_attribute *output, bool extended) { |
|
|
|
PARSE_DECL; |
|
|
|
char *ep; |
|
|
|
struct attribute_candidate *c; |
|
|
|
@ -665,31 +666,57 @@ static int parse_attribute_candidate(struct sdp_attribute *output) { |
|
|
|
if (!c->cand_parsed.type) |
|
|
|
return 0; |
|
|
|
|
|
|
|
if (!ice_has_related(c->cand_parsed.type)) |
|
|
|
goto done; |
|
|
|
if (ice_has_related(c->cand_parsed.type)) { |
|
|
|
// XXX guaranteed to be in order even with extended syntax? |
|
|
|
EXTRACT_TOKEN(u.candidate.raddr_str); |
|
|
|
EXTRACT_TOKEN(u.candidate.related_address_str); |
|
|
|
EXTRACT_TOKEN(u.candidate.rport_str); |
|
|
|
EXTRACT_TOKEN(u.candidate.related_port_str); |
|
|
|
|
|
|
|
EXTRACT_TOKEN(u.candidate.raddr_str); |
|
|
|
EXTRACT_TOKEN(u.candidate.related_address_str); |
|
|
|
EXTRACT_TOKEN(u.candidate.rport_str); |
|
|
|
EXTRACT_TOKEN(u.candidate.related_port_str); |
|
|
|
if (str_cmp(&c->raddr_str, "raddr")) |
|
|
|
return -1; |
|
|
|
if (str_cmp(&c->rport_str, "rport")) |
|
|
|
return -1; |
|
|
|
|
|
|
|
if (str_cmp(&c->raddr_str, "raddr")) |
|
|
|
return -1; |
|
|
|
if (str_cmp(&c->rport_str, "rport")) |
|
|
|
return -1; |
|
|
|
if (__parse_address(&c->cand_parsed.related.address, NULL, NULL, &c->related_address_str)) |
|
|
|
return 0; |
|
|
|
|
|
|
|
if (__parse_address(&c->cand_parsed.related.address, NULL, NULL, &c->related_address_str)) |
|
|
|
return 0; |
|
|
|
c->cand_parsed.related.port = strtoul(c->related_port_str.s, &ep, 10); |
|
|
|
if (ep == c->related_port_str.s) |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
c->cand_parsed.related.port = strtoul(c->related_port_str.s, &ep, 10); |
|
|
|
if (ep == c->related_port_str.s) |
|
|
|
return -1; |
|
|
|
if (extended) { |
|
|
|
while (true) { |
|
|
|
str field, value; |
|
|
|
if (str_token_sep(&field, value_str, ' ')) |
|
|
|
break; |
|
|
|
if (str_token_sep(&value, value_str, ' ')) |
|
|
|
break; |
|
|
|
if (!str_cmp(&field, "ufrag")) |
|
|
|
c->cand_parsed.ufrag = value; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
done: |
|
|
|
c->parsed = 1; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int sdp_parse_candidate(struct ice_candidate *cand, const str *s) { |
|
|
|
struct sdp_attribute attr = { |
|
|
|
.value = *s, |
|
|
|
}; |
|
|
|
|
|
|
|
if (parse_attribute_candidate(&attr, true)) |
|
|
|
return -1; |
|
|
|
if (!attr.u.candidate.parsed) |
|
|
|
return -1; |
|
|
|
*cand = attr.u.candidate.cand_parsed; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int parse_attribute_fingerprint(struct sdp_attribute *output) { |
|
|
|
PARSE_DECL; |
|
|
|
unsigned char *c; |
|
|
|
@ -992,7 +1019,7 @@ static int parse_attribute(struct sdp_attribute *a) { |
|
|
|
a->attr = ATTR_RTCP_MUX; |
|
|
|
break; |
|
|
|
case CSH_LOOKUP("candidate"): |
|
|
|
ret = parse_attribute_candidate(a); |
|
|
|
ret = parse_attribute_candidate(a, false); |
|
|
|
break; |
|
|
|
case CSH_LOOKUP("ice-ufrag"): |
|
|
|
a->attr = ATTR_ICE_UFRAG; |
|
|
|
|