support non-forced insertion of ice candidates

2.2
Richard Fuchs 12 years ago
parent eadbc1c3ab
commit 72f6cc97f9

@ -93,7 +93,7 @@ struct peer {
unsigned char idx;
struct callstream *up;
int desired_family;
str ice_ufrag[2];
str ice_ufrag;
str ice_pwd;
int kernelized:1;
int filled:1;

@ -33,6 +33,7 @@ struct sdp_connection {
struct sdp_attributes {
GQueue list;
GHashTable *hash;
GHashTable *lists_hash;
};
struct sdp_session {
@ -64,6 +65,18 @@ struct attribute_rtcp {
struct network_address address;
};
struct attribute_candidate {
str foundation;
str component_str;
str transport;
str priority_str;
/* incomplete */
unsigned long component;
unsigned long priority;
int parsed:1;
};
struct sdp_attribute {
str full_line, /* including a= and \r\n */
line_value, /* without a= and without \r\n */
@ -75,11 +88,13 @@ struct sdp_attribute {
enum {
ATTR_OTHER = 0,
ATTR_RTCP,
ATTR_CANDIDATE,
ATTR_ICE,
} attr;
union {
struct attribute_rtcp rtcp;
struct attribute_candidate candidate;
} u;
};
@ -210,6 +225,8 @@ static int parse_media(char *start, char *end, struct sdp_media *output) {
static void attrs_init(struct sdp_attributes *a) {
g_queue_init(&a->list);
a->hash = g_hash_table_new(str_hash, str_equal);
a->lists_hash = g_hash_table_new_full(str_hash, str_equal,
NULL, (GDestroyNotify) g_queue_free);
}
static int parse_attribute_rtcp(struct sdp_attribute *output) {
@ -236,6 +253,29 @@ static int parse_attribute_rtcp(struct sdp_attribute *output) {
return 0;
}
static int parse_attribute_candidate(struct sdp_attribute *output) {
char *end, *start, *ep;
start = output->value.s;
end = start + output->value.len;
output->attr = ATTR_CANDIDATE;
EXTRACT_TOKEN(u.candidate.foundation);
EXTRACT_TOKEN(u.candidate.component_str);
EXTRACT_TOKEN(u.candidate.transport);
EXTRACT_TOKEN(u.candidate.priority_str);
output->u.candidate.component = strtoul(output->u.candidate.component_str.s, &ep, 10);
if (ep == output->u.candidate.component_str.s)
return -1;
output->u.candidate.priority = strtoul(output->u.candidate.priority_str.s, &ep, 10);
if (ep == output->u.candidate.priority_str.s)
return -1;
output->u.candidate.parsed = 1;
return 0;
}
static void parse_attribute(struct sdp_attribute *a) {
a->name = a->line_value;
str_chr_str(&a->value, &a->name, ':');
@ -275,7 +315,7 @@ static void parse_attribute(struct sdp_attribute *a) {
break;
case 9:
if (!str_cmp(&a->name, "candidate"))
a->attr = ATTR_ICE;
parse_attribute_candidate(a);
else if (!str_cmp(&a->name, "ice-ufrag"))
a->attr = ATTR_ICE;
break;
@ -302,6 +342,7 @@ int sdp_parse(str *body, GQueue *sessions) {
struct sdp_attributes *attrs;
struct sdp_attribute *attr;
str *adj_s;
GQueue *attr_queue;
b = body->s;
end = str_end(body);
@ -389,6 +430,12 @@ int sdp_parse(str *body, GQueue *sessions) {
if (attr->key.s)
g_hash_table_insert(attrs->hash, &attr->key, attr);
attr_queue = g_hash_table_lookup(attrs->lists_hash, &attr->name);
if (!attr_queue)
g_hash_table_insert(attrs->lists_hash, &attr->name,
(attr_queue = g_queue_new()));
g_queue_push_tail(attr_queue, attr);
break;
case 'b':
@ -437,6 +484,7 @@ static void free_attributes(struct sdp_attributes *a) {
struct sdp_attribute *attr;
g_hash_table_destroy(a->hash);
g_hash_table_destroy(a->lists_hash);
while ((attr = g_queue_pop_head(&a->list))) {
g_slice_free1(sizeof(*attr), attr);
}
@ -757,6 +805,7 @@ static int process_session_attributes(struct sdp_chopper *chop, struct sdp_attri
switch (attr->attr) {
case ATTR_ICE:
case ATTR_CANDIDATE:
if (!flags->ice_remove && !flags->ice_force)
break;
goto strip;
@ -787,6 +836,7 @@ static int process_media_attributes(struct sdp_chopper *chop, struct sdp_attribu
switch (attr->attr) {
case ATTR_ICE:
case ATTR_CANDIDATE:
if (!flags->ice_remove && !flags->ice_force)
break;
goto strip;
@ -826,6 +876,39 @@ static int has_rtcp(struct sdp_session *session, struct sdp_media *media) {
return 0;
}
static unsigned long prio_calc(unsigned int pref) {
return (1 << 24) * 126 + (1 << 8) * pref + 256 * 1;
}
static unsigned long new_priority(struct sdp_media *media) {
str s;
GQueue *cands;
unsigned int pref;
unsigned long prio;
GList *l;
struct attribute_candidate *c;
pref = 65535;
prio = prio_calc(pref);
if (!media)
goto out;
str_init(&s, "candidate");
cands = g_hash_table_lookup(media->attributes.lists_hash, &s);
for (l = cands->head; l; l = l->next) {
c = l->data;
while (c->priority >= prio) {
pref--;
prio = prio_calc(pref);
}
}
out:
return prio;
}
int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
enum call_opmode opmode, struct sdp_ng_flags *flags, GHashTable *streamhash)
{
@ -835,6 +918,7 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
int off;
struct stream_input si, *sip;
struct streamrelay *rtp, *rtcp;
unsigned long priority;
off = opmode;
m = call->callstreams->head;
@ -858,18 +942,15 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
if (flags->ice_force) {
/* XXX locking here? */
create_random_string(call, &rtp->up->ice_ufrag[0], 8);
create_random_string(call, &rtp->up->ice_ufrag, 8);
create_random_string(call, &rtp->up->ice_pwd, 28);
copy_up_to_end_of(chop, &session->s);
chopper_append_c(chop, "a=ice-lite\r\na=ice-ufrag:");
chopper_append_str(chop, &rtp->up->ice_ufrag[0]);
chopper_append_str(chop, &rtp->up->ice_ufrag);
chopper_append_c(chop, "\r\na=ice-pwd:");
chopper_append_str(chop, &rtp->up->ice_pwd);
chopper_append_c(chop, "\r\n");
rtp->stun = 1;
rtcp->stun = 1;
}
for (k = session->media_streams.head; k; k = k->next) {
@ -907,17 +988,25 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call,
chopper_append_c(chop, "\r\n");
}
if (flags->ice_force) {
/* prio = (2^24) * 126 + (2^8) * 65535 + (256 - componentID) */
if (!flags->ice_remove) {
if (flags->ice_force) {
priority = new_priority(NULL);
rtp->stun = 1;
rtcp->stun = 1;
}
else
priority = new_priority(media);
chopper_append_c(chop, "a=candidate:");
chopper_append_str(chop, &ice_foundation_str);
chopper_append_c(chop, " 1 UDP 2130706431 ");
chopper_append_printf(chop, " 1 UDP %lu ", priority);
insert_ice_address(chop, flags, rtp);
chopper_append_c(chop, " typ host\r\n");
if (has_rtcp(session, media)) {
chopper_append_c(chop, "a=candidate:");
chopper_append_str(chop, &ice_foundation_str);
chopper_append_c(chop, " 2 UDP 2130706430 ");
chopper_append_printf(chop, " 2 UDP %lu ", priority - 1);
insert_ice_address(chop, flags, rtcp);
chopper_append_c(chop, " typ host\r\n");
}

@ -313,7 +313,7 @@ static int check_auth(str *msg, struct stun_attrs *attrs, struct peer *peer) {
str ufrag[2];
struct iovec iov[3];
if (!peer->ice_ufrag[0].s || !peer->ice_ufrag[0].len)
if (!peer->ice_ufrag.s || !peer->ice_ufrag.len)
return -1;
if (!peer->ice_pwd.s || !peer->ice_pwd.len)
return -1;
@ -327,7 +327,7 @@ static int check_auth(str *msg, struct stun_attrs *attrs, struct peer *peer) {
if (!ufrag[0].len || !ufrag[1].len)
return -1;
if (str_cmp_str(&ufrag[0], &peer->ice_ufrag[0]))
if (str_cmp_str(&ufrag[0], &peer->ice_ufrag))
return -1;
lenX = htons((attrs->msg_integrity_attr - msg->s) - 20 + 24);

Loading…
Cancel
Save