Browse Source

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
pull/1682/head
Richard Fuchs 3 years ago
parent
commit
b4a96be7f1
3 changed files with 63 additions and 30 deletions
  1. +38
    -11
      daemon/call.c
  2. +23
    -17
      daemon/call_interfaces.c
  3. +2
    -2
      include/call.h

+ 38
- 11
daemon/call.c View File

@ -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);


+ 23
- 17
daemon/call_interfaces.c View File

@ -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";


+ 2
- 2
include/call.h View File

@ -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);


Loading…
Cancel
Save