From b4a96be7f1526d73806adc89a78b0d719863cd82 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 26 Apr 2023 12:14:31 -0400 Subject: [PATCH] TT#146201 return offer/answer subscription objects Instead of just return the monologues involved in an offer/answer, return the respective subscription objects that have the monologues pointing to each other. This makes it possible to set flags within these objects. Change-Id: Id88e56e1bf164a75e2172d0df04316cde5d8a955 --- daemon/call.c | 49 +++++++++++++++++++++++++++++++--------- daemon/call_interfaces.c | 40 ++++++++++++++++++-------------- include/call.h | 4 ++-- 3 files changed, 63 insertions(+), 30 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index e14da307e..fd5c953d3 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2755,13 +2755,13 @@ unsigned int proto_num_ports(unsigned int sp_ports, struct call_media *media, st } /* called with call->master_lock held in W */ -int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, +int monologue_offer_answer(struct call_subscription *dialogue[2], GQueue *streams, struct sdp_ng_flags *flags) { struct call_media *media, *other_media; struct endpoint_map *em; - struct call_monologue *other_ml = dialogue[0]; - struct call_monologue *monologue = dialogue[1]; + struct call_monologue *other_ml = dialogue[0]->monologue; + struct call_monologue *monologue = dialogue[1]->monologue; unsigned int num_ports_this, num_ports_other; /* we must have a complete dialogue, even though the to-tag (monologue->tag) @@ -3025,6 +3025,14 @@ static void __subscribe_offer_answer_both_ways(struct call_monologue *a, struct __add_subscription(b, a, 0, &b_attrs); } +// return subscription objects, valid only immediately after __subscribe_offer_answer_both_ways +static void __offer_answer_get_subscriptions(struct call_monologue *a, struct call_monologue *b, + struct call_subscription *rets[2]) +{ + rets[0] = b->subscribers.head->data; + rets[1] = a->subscribers.head->data; +} + struct call_subscription *call_get_call_subscription(GHashTable *ht, struct call_monologue *ml) { @@ -4111,6 +4119,16 @@ static void __tags_associate(struct call_monologue *a, struct call_monologue *b) g_hash_table_insert(b->associated_tags, a, a); } +// return subscription objects if they haven't been filled in yet +static void __tags_get_subscriptions(struct call_monologue *a, struct call_monologue *b, + struct call_subscription *rets[2]) +{ + if (rets[0]) + return; + rets[0] = call_get_call_subscription(b->subscribers_ht, a); + rets[1] = call_get_call_subscription(a->subscribers_ht, b); +} + /** * Check whether the call object contains some other monologues, which can have own associations. */ @@ -4135,8 +4153,10 @@ static bool call_monologues_associations_left(struct call * c) { * using the given To-tag, if this associated monologue didn't have a tag before. * * Must be called with call->master_lock held in W. + * + * `dialogue` must be initialised to zero. */ -static int call_get_monologue_new(struct call_monologue *dialogue[2], struct call *call, +static int call_get_monologue_new(struct call_subscription *dialogue[2], struct call *call, const str *fromtag, const str *totag, const str *viabranch) { @@ -4181,6 +4201,7 @@ static int call_get_monologue_new(struct call_monologue *dialogue[2], struct cal // use existing to-tag __monologue_unkernelize(csm, "dialogue association changed"); __subscribe_offer_answer_both_ways(ret, csm); + __offer_answer_get_subscriptions(ret, csm, dialogue); break; } break; // there should only be one @@ -4210,6 +4231,7 @@ static int call_get_monologue_new(struct call_monologue *dialogue[2], struct cal /* previously seen branch. use it */ __monologue_unkernelize(os, "dialogue/branch association changed"); __subscribe_offer_answer_both_ways(ret, os); + __offer_answer_get_subscriptions(ret, os, dialogue); goto ok_check_tag; } @@ -4219,6 +4241,7 @@ new_branch: __C_DBG("create new \"other side\" monologue for viabranch "STR_FORMAT, STR_FMT0(viabranch)); os = __monologue_create(call); __subscribe_offer_answer_both_ways(ret, os); + __offer_answer_get_subscriptions(ret, os, dialogue); __monologue_viabranch(os, viabranch); ok_check_tag: @@ -4237,8 +4260,7 @@ ok_check_tag: if (G_UNLIKELY(!os)) return -1; __tags_associate(ret, os); - dialogue[0] = ret; - dialogue[1] = os; + __tags_get_subscriptions(ret, os, dialogue); return 0; } @@ -4250,8 +4272,11 @@ ok_check_tag: * The request will be treated as a brand new offer, * in case the To-tag is still not know for this call. * - * The function must be called with call->master_lock held in W */ -static int call_get_dialogue(struct call_monologue *dialogue[2], struct call *call, const str *fromtag, + * The function must be called with call->master_lock held in W. + * + * `dialogue` must be initialised to zero. + */ +static int call_get_dialogue(struct call_subscription *dialogue[2], struct call *call, const str *fromtag, const str *totag, const str *viabranch) { @@ -4318,23 +4343,25 @@ tag_setup: dialogue_unkernelize(ft, "dialogue signalling event"); dialogue_unkernelize(tt, "dialogue signalling event"); __subscribe_offer_answer_both_ways(ft, tt); + __offer_answer_get_subscriptions(ft, tt, dialogue); done: __monologue_unkernelize(ft, "dialogue signalling event"); dialogue_unkernelize(ft, "dialogue signalling event"); __tags_associate(ft, tt); - dialogue[0] = ft; - dialogue[1] = tt; + __tags_get_subscriptions(ft, tt, dialogue); return 0; } /* fromtag and totag strictly correspond to the directionality of the message, not to the actual * SIP headers. IOW, the fromtag corresponds to the monologue sending this message, even if the * tag is actually from the TO header of the SIP message (as it would be in a 200 OK) */ -int call_get_mono_dialogue(struct call_monologue *dialogue[2], struct call *call, const str *fromtag, +int call_get_mono_dialogue(struct call_subscription *dialogue[2], struct call *call, const str *fromtag, const str *totag, const str *viabranch) { + dialogue[0] = dialogue[1] = NULL; + if (!totag || !totag->s) /* initial offer */ return call_get_monologue_new(dialogue, call, fromtag, NULL, viabranch); return call_get_dialogue(dialogue, call, fromtag, totag, viabranch); diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index ee70ddf64..7c8569fe0 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -161,7 +161,7 @@ static str *call_update_lookup_udp(char **out, enum call_opmode opmode, const ch const endpoint_t *sin) { struct call *c; - struct call_monologue *dialogue[2]; + struct call_subscription *dialogue[2]; GQueue q = G_QUEUE_INIT; struct stream_params sp; str *ret, callid, viabranch, fromtag, totag = STR_NULL; @@ -186,10 +186,13 @@ static str *call_update_lookup_udp(char **out, enum call_opmode opmode, const ch if (call_get_mono_dialogue(dialogue, c, &fromtag, &totag, NULL)) goto ml_fail; + struct call_monologue *from_ml = dialogue[0]->monologue; + struct call_monologue *to_ml = dialogue[1]->monologue; + if (opmode == OP_OFFER) { - dialogue[0]->tagtype = FROM_TAG; + from_ml->tagtype = FROM_TAG; } else { - dialogue[0]->tagtype = TO_TAG; + from_ml->tagtype = TO_TAG; } if (addr_parse_udp(&sp, out)) @@ -202,13 +205,13 @@ static str *call_update_lookup_udp(char **out, enum call_opmode opmode, const ch if (i) goto unlock_fail; - ret = streams_print(dialogue[1]->medias, + ret = streams_print(to_ml->medias, sp.index, sp.index, out[RE_UDP_COOKIE], SAF_UDP); rwlock_unlock_w(&c->master_lock); redis_update_onekey(c, rtpe_redis_write); - gettimeofday(&(dialogue[0]->started), NULL); + gettimeofday(&(from_ml->started), NULL); ilog(LOG_INFO, "Returning to SIP proxy: "STR_FORMAT"", STR_FMT(ret)); goto out; @@ -308,7 +311,7 @@ INLINE void call_unlock_release_update(struct call **c) { static str *call_request_lookup_tcp(char **out, enum call_opmode opmode) { struct call *c; - struct call_monologue *dialogue[2]; + struct call_subscription *dialogue[2]; AUTO_CLEANUP(GQueue s, sdp_streams_free) = G_QUEUE_INIT; str *ret = NULL, callid, fromtag, totag = STR_NULL; GHashTable *infohash; @@ -344,7 +347,7 @@ static str *call_request_lookup_tcp(char **out, enum call_opmode opmode) { if (monologue_offer_answer(dialogue, &s, NULL)) goto out2; - ret = streams_print(dialogue[1]->medias, 1, s.length, NULL, SAF_TCP); + ret = streams_print(dialogue[1]->monologue->medias, 1, s.length, NULL, SAF_TCP); out2: call_unlock_release_update(&c); @@ -1945,7 +1948,7 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t AUTO_CLEANUP(GQueue parsed, sdp_free) = G_QUEUE_INIT; AUTO_CLEANUP(GQueue streams, sdp_streams_free) = G_QUEUE_INIT; struct call *call; - struct call_monologue *dialogue[2]; + struct call_subscription *dialogue[2]; int ret; AUTO_CLEANUP(struct sdp_ng_flags flags, call_ng_free_flags); struct sdp_chopper *chopper; @@ -2033,16 +2036,19 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t goto out; } + struct call_monologue *from_ml = dialogue[0]->monologue; + struct call_monologue *to_ml = dialogue[1]->monologue; + if (opmode == OP_OFFER) { - dialogue[0]->tagtype = FROM_TAG; + from_ml->tagtype = FROM_TAG; } else { - dialogue[0]->tagtype = TO_TAG; + from_ml->tagtype = TO_TAG; } chopper = sdp_chopper_new(&sdp); bencode_buffer_destroy_add(output->buffer, (free_func_t) sdp_chopper_destroy, chopper); - update_metadata_monologue(dialogue[0], &flags.metadata); + update_metadata_monologue(from_ml, &flags.metadata); detect_setup_recording(call, &flags); if (flags.drop_traffic_start) { @@ -2055,20 +2061,20 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t ret = monologue_offer_answer(dialogue, &streams, &flags); if (!ret) - ret = sdp_replace(chopper, &parsed, dialogue[1], &flags); + ret = sdp_replace(chopper, &parsed, to_ml, &flags); if (!ret) - save_last_sdp(dialogue[0], &sdp, &parsed, &streams); + save_last_sdp(from_ml, &sdp, &parsed, &streams); struct recording *recording = call->recording; if (recording != NULL) { - meta_write_sdp_before(recording, &sdp, dialogue[0], opmode); + meta_write_sdp_before(recording, &sdp, from_ml, opmode); meta_write_sdp_after(recording, chopper->output, - dialogue[0], opmode); + from_ml, opmode); recording_response(recording, output); } - dequeue_sdp_fragments(dialogue[0]); + dequeue_sdp_fragments(from_ml); rwlock_unlock_w(&call->master_lock); @@ -2079,7 +2085,7 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t } obj_put(call); - gettimeofday(&(dialogue[0]->started), NULL); + gettimeofday(&(from_ml->started), NULL); errstr = "Error rewriting SDP"; diff --git a/include/call.h b/include/call.h index b7981ad05..104498d8a 100644 --- a/include/call.h +++ b/include/call.h @@ -721,13 +721,13 @@ void call_subscriptions_clear(GQueue *q); struct call *call_get_or_create(const str *callid, bool foreign, bool exclusive); struct call *call_get_opmode(const str *callid, enum call_opmode opmode); void call_make_own_foreign(struct call *c, bool foreign); -int call_get_mono_dialogue(struct call_monologue *dialogue[2], struct call *call, const str *fromtag, +int call_get_mono_dialogue(struct call_subscription *dialogue[2], struct call *call, const str *fromtag, const str *totag, const str *viabranch); struct call_monologue *call_get_monologue(struct call *call, const str *fromtag); struct call_monologue *call_get_or_create_monologue(struct call *call, const str *fromtag); struct call *call_get(const str *callid); -int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, struct sdp_ng_flags *flags); +int monologue_offer_answer(struct call_subscription *dialogue[2], GQueue *streams, struct sdp_ng_flags *flags); void codecs_offer_answer(struct call_media *media, struct call_media *other_media, struct stream_params *sp, struct sdp_ng_flags *flags); int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_flags *flags);