From 811fe2b59eae17e783a168c6b04ab72e362361af Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 21 May 2015 08:57:42 -0400 Subject: [PATCH] support branched offer with previously unseen to-tag --- daemon/call.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 7e49cb624..233e91f02 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2872,19 +2872,22 @@ static void __monologue_destroy(struct call_monologue *monologue) { } /* must be called with call->master_lock held in W */ -static struct call_monologue *call_get_monologue(struct call *call, const str *fromtag, const str *viabranch) { +static struct call_monologue *call_get_monologue(struct call *call, const str *fromtag, const str *totag, + const str *viabranch) +{ struct call_monologue *ret, *os; __C_DBG("getting monologue for tag '"STR_FORMAT"' in call '"STR_FORMAT"'", STR_FMT(fromtag), STR_FMT(&call->callid)); ret = g_hash_table_lookup(call->tags, fromtag); + /* XXX reverse the conditional */ if (ret) { __C_DBG("found existing monologue"); __monologue_unkernelize(ret); __monologue_unkernelize(ret->active_dialogue); if (!viabranch) - return ret; + goto ok_check_tag; /* check the viabranch. if it's not known, then this is a branched offer and we need * to create a new "other side" for this branch. */ @@ -2892,17 +2895,17 @@ static struct call_monologue *call_get_monologue(struct call *call, const str *f /* previous "other side" hasn't been tagged with the via-branch, so we'll just * use this one and tag it */ __monologue_viabranch(ret->active_dialogue, viabranch); - return ret; + goto ok_check_tag; } if (!str_cmp_str(&ret->active_dialogue->viabranch, viabranch)) - return ret; /* dialogue still intact */ + goto ok_check_tag; /* dialogue still intact */ os = g_hash_table_lookup(call->viabranches, viabranch); if (os) { /* previously seen branch. use it */ __monologue_unkernelize(os); os->active_dialogue = ret; ret->active_dialogue = os; - return ret; + goto ok_check_tag; } goto new_branch; } @@ -2917,6 +2920,9 @@ new_branch: ret->active_dialogue = __monologue_create(call); __monologue_viabranch(ret->active_dialogue, viabranch); +ok_check_tag: + if (totag && totag->s && !ret->active_dialogue->tag.s) + __monologue_tag(ret->active_dialogue, totag); return ret; } @@ -2929,6 +2935,11 @@ static struct call_monologue *call_get_dialogue(struct call *call, const str *fr __C_DBG("getting dialogue for tags '"STR_FORMAT"'<>'"STR_FORMAT"' in call '"STR_FORMAT"'", STR_FMT(fromtag), STR_FMT(totag), STR_FMT(&call->callid)); + /* we start with the to-tag. if it's not known, we treat it as a branched offer */ + tt = g_hash_table_lookup(call->tags, totag); + if (!tt) + return call_get_monologue(call, fromtag, totag, viabranch); + /* if the from-tag is known already, return that */ ft = g_hash_table_lookup(call->tags, fromtag); if (ft) { @@ -2945,11 +2956,6 @@ static struct call_monologue *call_get_dialogue(struct call *call, const str *fr ft = g_hash_table_lookup(call->viabranches, viabranch); } - /* the to-tag has to be known. it's an error if it isn't */ - tt = g_hash_table_lookup(call->tags, totag); - if (!tt) - return NULL; - if (!ft) { /* if we don't have a fromtag monologue yet, we can use a half-complete dialogue * from the totag if there is one. otherwise we have to create a new one. */ @@ -2983,7 +2989,7 @@ struct call_monologue *call_get_mono_dialogue(struct call *call, const str *from const str *viabranch) { if (!totag || !totag->s) /* initial offer */ - return call_get_monologue(call, fromtag, viabranch); + return call_get_monologue(call, fromtag, NULL, viabranch); return call_get_dialogue(call, fromtag, totag, viabranch); }