From c0fab9b47d0d1ee45ca1a9359ae6ad10288fb97b Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 26 Mar 2015 16:06:06 -0400 Subject: [PATCH] various fixes related to ICE negotation and rtcp-mux closes #92 --- daemon/call.c | 12 +++++++-- daemon/ice.c | 68 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index c92d192e7..34255e1d9 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -146,6 +146,7 @@ const char * get_tag_type_text(enum tag_type t) { } static void determine_handler(struct packet_stream *in, const struct packet_stream *out); +static void __call_media_state_machine(struct call_media *m); static int __k_null(struct rtpengine_srtp *s, struct packet_stream *); static int __k_srtp_encrypt(struct rtpengine_srtp *s, struct packet_stream *); @@ -645,7 +646,7 @@ static int stream_packet(struct stream_fd *sfd, str *s, struct sockaddr_in6 *fsi if (!stun_ret) goto unlock_out; if (stun_ret == 1) { - call_stream_state_machine(stream); + __call_media_state_machine(media); mutex_lock(&stream->in_lock); /* for the jump */ goto kernel_check; } @@ -1904,6 +1905,13 @@ enum call_stream_state call_stream_state_machine(struct packet_stream *ps) { return CSS_RUNNING; } +static void __call_media_state_machine(struct call_media *m) { + GList *l; + + for (l = m->streams.head; l; l = l->next) + call_stream_state_machine(l->data); +} + static int __init_stream(struct packet_stream *ps) { struct call_media *media = ps->media; struct call *call = ps->call; @@ -2472,7 +2480,6 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, /* control rtcp-mux */ __rtcp_mux_logic(flags, media, other_media); - /* XXX update ICE if rtcp-mux changes */ /* SDES and DTLS */ __generate_crypto(flags, media, other_media); @@ -2548,6 +2555,7 @@ init: /* we are now ready to fire up ICE if so desired and requested */ ice_update(other_media->ice_agent, sp); + ice_update(media->ice_agent, NULL); /* this is in case rtcp-mux has changed */ } return 0; diff --git a/daemon/ice.c b/daemon/ice.c index 4b43ae6b9..9ab3404c6 100644 --- a/daemon/ice.c +++ b/daemon/ice.c @@ -317,8 +317,9 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { int recalc = 0; unsigned int comps; struct packet_stream *components[MAX_COMPONENTS], *ps; + GQueue *candidates; - if (!ag || !sp) + if (!ag) return; media = ag->media; @@ -326,19 +327,25 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { __role_change(ag, MEDIA_ISSET(media, ICE_CONTROLLING)); - /* check for ICE restarts */ - if (ag->ufrag[0].s && sp->ice_ufrag.s && str_cmp_str(&ag->ufrag[0], &sp->ice_ufrag)) - __ice_restart(ag); - else if (ag->pwd[0].s && sp->ice_pwd.s && str_cmp_str(&ag->pwd[0], &sp->ice_pwd)) - __ice_restart(ag); - else if (ag->local_interface != media->interface) - __ice_restart(ag); - - /* update remote info */ - if (sp->ice_ufrag.s) - call_str_cpy(call, &ag->ufrag[0], &sp->ice_ufrag); - if (sp->ice_pwd.s) - call_str_cpy(call, &ag->pwd[0], &sp->ice_pwd); + if (sp) { + /* check for ICE restarts */ + if (ag->ufrag[0].s && sp->ice_ufrag.s && str_cmp_str(&ag->ufrag[0], &sp->ice_ufrag)) + __ice_restart(ag); + else if (ag->pwd[0].s && sp->ice_pwd.s && str_cmp_str(&ag->pwd[0], &sp->ice_pwd)) + __ice_restart(ag); + else if (ag->local_interface != media->interface) + __ice_restart(ag); + + /* update remote info */ + if (sp->ice_ufrag.s) + call_str_cpy(call, &ag->ufrag[0], &sp->ice_ufrag); + if (sp->ice_pwd.s) + call_str_cpy(call, &ag->pwd[0], &sp->ice_pwd); + + candidates = &sp->ice_candidates; + } + else /* this is a dummy update in case rtcp-mux has changed */ + candidates = &ag->remote_candidates; /* get our component streams */ ZERO(components); @@ -349,7 +356,7 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { components[1] = NULL; comps = 0; - for (l = sp->ice_candidates.head; l; l = l->next) { + for (l = candidates->head; l; l = l->next) { if (ag->remote_candidates.length >= MAX_ICE_CANDIDATES) { ilog(LOG_WARNING, "Maxmimum number of ICE candidates exceeded"); break; @@ -360,15 +367,16 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { /* skip invalid */ if (!cand->component_id || cand->component_id > G_N_ELEMENTS(components)) continue; - /* skip if we don't have a candidate of our own */ ps = components[cand->component_id - 1]; - if (!ps) - continue; - comps = MAX(comps, cand->component_id); + if (ps) /* only count active components */ + comps = MAX(comps, cand->component_id); - /* check for duplicates */ dup = g_hash_table_lookup(ag->candidate_hash, cand); + if (!sp && dup) /* this isn't a real update, so only check pairings */ + goto pair; + + /* check for duplicates */ if (dup) { /* if this is peer reflexive, we've learned it through STUN. * otherwise it's simply one we've seen before. */ @@ -410,6 +418,9 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { g_hash_table_insert(ag->foundation_hash, dup, dup); +pair: + if (!ps) + continue; for (k = ag->local_interface->list.head; k; k = k->next) { /* skip duplicates here also */ if (__pair_lookup(ag, dup, k->data)) @@ -1088,8 +1099,10 @@ int ice_request(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_a g_tree_insert(ag->nominated_pairs, pair, pair); - if (PAIR_ISSET(pair, SUCCEEDED)) + if (PAIR_ISSET(pair, SUCCEEDED)) { + PAIR_SET(pair, VALID); g_tree_insert(ag->valid_pairs, pair, pair); + } if (!AGENT_ISSET(ag, CONTROLLING)) ret = __check_valid(ag); @@ -1129,7 +1142,7 @@ static int __check_succeeded_complete(struct ice_agent *ag) { int ice_response(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_addr *dst, struct stun_attrs *attrs, u_int32_t transaction[3]) { - struct ice_candidate_pair *pair; + struct ice_candidate_pair *pair, *opair; struct ice_agent *ag; struct call_media *media = ps->media; const char *err; @@ -1222,20 +1235,21 @@ int ice_response(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_ cand = __foundation_lookup(ag, &pair->remote_candidate->foundation, component); if (!cand) continue; - pair = __pair_lookup(ag, cand, ifa); - if (!pair) + opair = __pair_lookup(ag, cand, ifa); + if (!opair) continue; - if (PAIR_ISSET(pair, FAILED)) + if (PAIR_ISSET(opair, FAILED)) continue; - if (!PAIR_CLEAR(pair, FROZEN)) + if (!PAIR_CLEAR(opair, FROZEN)) continue; - ilog(LOG_DEBUG, "Unfreezing related ICE pair "PAIR_FORMAT, PAIR_FMT(pair)); + ilog(LOG_DEBUG, "Unfreezing related ICE pair "PAIR_FORMAT, PAIR_FMT(opair)); } /* if this was previously nominated by the peer, it's now valid */ if (PAIR_ISSET(pair, NOMINATED)) { + PAIR_SET(pair, VALID); g_tree_insert(ag->valid_pairs, pair, pair); if (!AGENT_ISSET(ag, CONTROLLING))