diff --git a/daemon/call.c b/daemon/call.c index 07f75bcf1..1c2692349 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -5875,13 +5875,14 @@ call_t *call_get_opmode(const str *callid, enum ng_opmode opmode) { * * Must be called with call->master_lock held in W. */ -struct call_monologue *__monologue_create(call_t *call) { +struct call_monologue *__monologue_create(call_t *call, const str *callid) { struct call_monologue *ret; dbg_int("creating new monologue"); ret = uid_alloc(&call->monologues); ret->call = call; + ret->call_id = call_str_cpy(callid); ret->created_us = rtpe_now; ret->associated_tags = g_hash_table_new(g_direct_hash, g_direct_equal); ret->medias = medias_arr_new(); @@ -6139,10 +6140,10 @@ static struct call_monologue *call_get_monologue_alias(call_t *call, const str * * * Must be called with call->master_lock held in W. */ -struct call_monologue *call_get_or_create_monologue(call_t *call, const str *fromtag) { +struct call_monologue *call_get_or_create_monologue(call_t *call, const str *callid, const str *fromtag) { struct call_monologue *ret = call_get_monologue(call, fromtag); if (!ret) { - ret = __monologue_create(call); + ret = __monologue_create(call, callid); __monologue_tag(ret, fromtag); } return ret; @@ -6190,7 +6191,10 @@ static bool call_monologues_associations_left(call_t * c) { * * `dialogue` must be initialised to zero. */ -static int call_get_monologue_new(struct call_monologue *monologues[2], call_t *call, +__attribute__((nonnull(1, 2, 3, 4))) +static int call_get_monologue_new(struct call_monologue *monologues[2], + call_t *call, + const str *callid, const str *fromtag, const str *totag, const str *viabranch, @@ -6204,7 +6208,7 @@ static int call_get_monologue_new(struct call_monologue *monologues[2], call_t * ret = call_get_monologue_alias(call, fromtag, flags, &flags->sdp, ep); if (!ret) { /* this is a brand new offer */ - ret = __monologue_create(call); + ret = __monologue_create(call, callid); __monologue_tag(ret, fromtag); goto new_branch; } @@ -6238,7 +6242,7 @@ static int call_get_monologue_new(struct call_monologue *monologues[2], call_t * * another monologue without to-tag (to be filled in later) */ new_branch: dbg_int("create new \"other side\" monologue for viabranch "STR_FORMAT, STR_FMT0(viabranch)); - os = __monologue_create(call); + os = __monologue_create(call, callid); __monologue_viabranch(os, viabranch); goto finish; @@ -6282,7 +6286,10 @@ finish: * * `dialogue` must be initialised to zero. */ -static int call_get_dialogue(struct call_monologue *monologues[2], call_t *call, +__attribute__((nonnull(1, 2, 3, 4))) +static int call_get_dialogue(struct call_monologue *monologues[2], + call_t *call, + const str *callid, const str *fromtag, const str *totag, const str *viabranch, @@ -6290,7 +6297,7 @@ static int call_get_dialogue(struct call_monologue *monologues[2], call_t *call, { struct call_monologue *ft, *tt; - dbg_int("getting dialogue for tags '"STR_FORMAT"'<>'"STR_FORMAT"' in call '"STR_FORMAT"'", + dbg_int("getting dialogue for tags '" STR_FORMAT "'<>'" STR_FORMAT "' in call '" STR_FORMAT "'", STR_FMT(fromtag), STR_FMT(totag), STR_FMT(&call->callid)); /* ft - is always this side's tag (in offer it's message's from-tag, in answer it's message's to-tag) @@ -6300,7 +6307,7 @@ static int call_get_dialogue(struct call_monologue *monologues[2], call_t *call, /* we start with the to-tag. if it's not known, we treat it as a branched offer */ tt = call_get_monologue(call, totag); if (!tt) - return call_get_monologue_new(monologues, call, fromtag, totag, viabranch, flags, ep); + return call_get_monologue_new(monologues, call, callid, fromtag, totag, viabranch, flags, ep); /* if the from-tag is known already, return that */ ft = call_get_monologue_alias(call, fromtag, flags, &flags->sdp, ep); @@ -6353,14 +6360,14 @@ static int call_get_dialogue(struct call_monologue *monologues[2], call_t *call, * hence `ft->tag` has to be empty at this stage. */ if (!ft) - ft = __monologue_create(call); + ft = __monologue_create(call, callid); else if (ft->tag.s) { // Allow an updated/changed to-tag in answers unless the flag to // suppress this feature is set. A changed to-tag will be stored // as a tag alias. if (!flags || flags->opmode != OP_ANSWER || flags->new_branch || (ML_ISSET(ft, FINAL_RESPONSE) && !flags->provisional)) - ft = __monologue_create(call); + ft = __monologue_create(call, callid); } tag_setup: @@ -6388,7 +6395,9 @@ done: /* 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 *monologues[2], call_t *call, +int call_get_mono_dialogue(struct call_monologue *monologues[2], + call_t *call, + const str *callid, const str *fromtag, const str *totag, const str *viabranch, @@ -6396,9 +6405,9 @@ int call_get_mono_dialogue(struct call_monologue *monologues[2], call_t *call, { /* initial offer */ if (!totag || !totag->s) - return call_get_monologue_new(monologues, call, fromtag, NULL, viabranch, flags, ep); + return call_get_monologue_new(monologues, call, callid, fromtag, NULL, viabranch, flags, ep); - return call_get_dialogue(monologues, call, fromtag, totag, viabranch, flags, ep); + return call_get_dialogue(monologues, call, callid, fromtag, totag, viabranch, flags, ep); } static void media_stop(struct call_media *m) { diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 5144db7ed..658236aa1 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -180,7 +180,7 @@ static str call_update_lookup_udp(char **out, enum ng_opmode opmode, const char* updated_created_from(c, addr); - if (call_get_mono_dialogue(monologues, c, &fromtag, &totag, NULL, NULL, NULL)) + if (call_get_mono_dialogue(monologues, c, &callid, &fromtag, &totag, NULL, NULL, NULL)) goto ml_fail; struct call_monologue *from_ml = monologues[0]; @@ -339,7 +339,7 @@ static str call_request_lookup_tcp(char **out, enum ng_opmode opmode) { str_swap(&fromtag, &totag); } - if (call_get_mono_dialogue(monologues, c, &fromtag, &totag, NULL, NULL, NULL)) { + if (call_get_mono_dialogue(monologues, c, &callid, &fromtag, &totag, NULL, NULL, NULL)) { ilog(LOG_WARNING, "Invalid dialogue association"); goto out2; } @@ -621,7 +621,7 @@ static const char *call_offer_answer_ng(ng_command_ctx_t *ctx, const char *addr) call_ngb_hold_ref(call, ctx->ngbuf); errstr = "Invalid dialogue association"; - if (call_get_mono_dialogue(monologues, call, &flags.from_tag, &flags.to_tag, + if (call_get_mono_dialogue(monologues, call, &flags.call_id, &flags.from_tag, &flags.to_tag, flags.via_branch.s ? &flags.via_branch : NULL, &flags, streams.length ? &streams.head->data->rtp_endpoint : NULL)) { goto out; @@ -2121,7 +2121,7 @@ const char *call_publish_ng(ng_command_ctx_t *ctx, const char *addr) { return NULL; updated_created_from(call, addr); - struct call_monologue *ml = call_get_or_create_monologue(call, &flags.from_tag); + struct call_monologue *ml = call_get_or_create_monologue(call, &flags.call_id, &flags.from_tag); ret = monologue_publish(ml, &streams, &flags); if (ret) @@ -2191,7 +2191,7 @@ const char *call_subscribe_request_ng(ng_command_ctx_t *ctx) { g_autoptr(call_t) call = t_queue_pop_head(&calls); - struct call_monologue *dest_ml = call_get_or_create_monologue(call, &flags.to_tag); + struct call_monologue *dest_ml = call_get_or_create_monologue(call, &flags.call_id, &flags.to_tag); int ret = monologue_subscribe_request(&mq, dest_ml, &flags); if (ret) @@ -2430,7 +2430,7 @@ const char *call_connect_ng(ng_command_ctx_t *ctx) { if (!call) return "Failed to merge two calls into one (tag collision)"; - struct call_monologue *dest_ml = call_get_or_create_monologue(call, &flags.to_tag); + struct call_monologue *dest_ml = call_get_or_create_monologue(call, &flags.call_id, &flags.to_tag); if (!dest_ml) return "To-tag not found"; @@ -2496,7 +2496,7 @@ const char *call_transform_ng(ng_command_ctx_t *ctx) { flags.from_tag = STR_LEN(rand_hex_str(rand_from_tag, 32), 64); call = call_get_or_create(&flags.call_id, false); - struct call_monologue *ml = call_get_or_create_monologue(call, &flags.from_tag); + struct call_monologue *ml = call_get_or_create_monologue(call, &flags.call_id, &flags.from_tag); g_auto(medias_q) mq = TYPED_GQUEUE_INIT; if (!monologue_transform(ml, &flags, &mq)) @@ -2546,7 +2546,7 @@ const char *call_create_ng(ng_command_ctx_t *ctx) { flags.from_tag = STR_LEN(rand_hex_str(rand_from_tag, 32), 64); call = call_get_or_create(&flags.call_id, false); - struct call_monologue *ml = call_get_or_create_monologue(call, &flags.from_tag); + struct call_monologue *ml = call_get_or_create_monologue(call, &flags.call_id, &flags.from_tag); if (!monologue_call_create(ml, &flags)) return "failed to set up call/monologue"; diff --git a/daemon/codec.c b/daemon/codec.c index dcad65427..acf00bc9e 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -648,7 +648,7 @@ static const char *__make_transform_handler(struct codec_handler *handler) { // create dedicated monologue and dedicated call_media to send media to the // remote rtpengine and forward received media to its designated destination - tfh->transform_ml = call_get_or_create_monologue(call, STR_PTR("transform handler")); + tfh->transform_ml = call_get_or_create_monologue(call, &ml->call_id, STR_PTR("transform handler")); tfh->transform_media = call_make_transform_media(tfh->transform_ml, &media->type, media->type_id, &STR_NULL, &tcc->transform, &tcc->local_interface); diff --git a/daemon/janus.c b/daemon/janus.c index 25ad92804..cf2cfe782 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -115,14 +115,19 @@ static uint64_t jr_str_int(JsonReader *r) { } -static struct call_monologue *janus_get_monologue(uint64_t handle_id, call_t *call, - struct call_monologue *(*fn)(call_t *, const str *)) +static struct call_monologue *janus_call_get_monologue(call_t *c, const str *callid, const str *tag) { + return call_get_monologue(c, tag); +} + + +static struct call_monologue *janus_get_monologue(uint64_t handle_id, call_t *call, const str *callid, + struct call_monologue *(*fn)(call_t *, const str *, const str *)) { g_autoptr(char) handle_buf = NULL; handle_buf = g_strdup_printf("%" PRIu64, handle_id); str handle_str = STR(handle_buf); - return fn(call, &handle_str); + return fn(call, callid, &handle_str); } @@ -404,7 +409,8 @@ static void janus_publishers_list(JsonBuilder *builder, call_t *call, struct jan continue; // get monologue - struct call_monologue *ml = janus_get_monologue(*handle_id_ptr, call, call_get_monologue); + struct call_monologue *ml = janus_get_monologue(*handle_id_ptr, call, NULL, + janus_call_get_monologue); if (!ml) continue; @@ -437,7 +443,7 @@ static const char *janus_videoroom_join_sub(struct janus_handle *handle, struct t_hash_table_insert(room->subscribers, uint64_dup(handle->id), uint64_dup(feed_id)); // add the subscription - struct call_monologue *source_ml = janus_get_monologue(*feed_handle, call, call_get_monologue); + struct call_monologue *source_ml = janus_get_monologue(*feed_handle, call, NULL, janus_call_get_monologue); if (!source_ml) return "Feed not found"; @@ -616,7 +622,7 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan if (!medias.length) return "No feeds to subscribe to given"; - struct call_monologue *dest_ml = janus_get_monologue(handle->id, call, + struct call_monologue *dest_ml = janus_get_monologue(handle->id, call, &room->call_id, call_get_or_create_monologue); g_auto(sdp_ng_flags) flags; @@ -856,7 +862,7 @@ static const char *janus_videoroom_configure(struct websocket_message *wm, struc if (!sdp_streams(&parsed, &streams, &flags)) return "Incomplete SDP specification"; - ml = janus_get_monologue(handle->id, call, call_get_or_create_monologue); + ml = janus_get_monologue(handle->id, call, &room->call_id, call_get_or_create_monologue); // accept unsupported codecs if necessary flags.accept_any = 1; @@ -885,7 +891,7 @@ static const char *janus_videoroom_configure(struct websocket_message *wm, struc } else { // reconfigure existing publisher - ml = janus_get_monologue(handle->id, call, call_get_monologue); + ml = janus_get_monologue(handle->id, call, NULL, janus_call_get_monologue); if (!ml) return "Not an existing publisher"; } @@ -980,12 +986,12 @@ static const char *janus_videoroom_start(struct websocket_message *wm, struct ja if (!feed_handle) return "No such feed exists"; - struct call_monologue *source_ml = janus_get_monologue(*feed_handle, call, call_get_monologue); + struct call_monologue *source_ml = janus_get_monologue(*feed_handle, call, NULL, janus_call_get_monologue); if (!source_ml) return "Feed not found"; // XXX verify that dest_ml is subscribed to source_ml - struct call_monologue *dest_ml = janus_get_monologue(handle->id, call, call_get_monologue); + struct call_monologue *dest_ml = janus_get_monologue(handle->id, call, NULL, janus_call_get_monologue); if (!dest_ml) return "Subscriber not found"; @@ -1041,7 +1047,7 @@ static const char *janus_videoroom_unpublish(struct websocket_message *wm, struc // notify other publishers janus_notify_publishers(room_id, handle->id, NULL, *feed_id, janus_notify_publishers_unpublished); - struct call_monologue *ml = janus_get_monologue(handle->id, call, call_get_monologue); + struct call_monologue *ml = janus_get_monologue(handle->id, call, NULL, janus_call_get_monologue); if (ml) monologue_destroy(ml); @@ -1360,7 +1366,7 @@ static void janus_destroy_handle(struct janus_handle *handle) { call_t *call = call_get(&room->call_id); if (call) { // remove publisher monologue - struct call_monologue *ml = janus_get_monologue(handle_id, call, call_get_monologue); + struct call_monologue *ml = janus_get_monologue(handle_id, call, NULL, janus_call_get_monologue); if (ml) monologue_destroy(ml); @@ -1377,7 +1383,7 @@ static void janus_destroy_handle(struct janus_handle *handle) { call_t *call = call_get(&room->call_id); if (call) { // remove subscriber monologue - struct call_monologue *ml = janus_get_monologue(handle_id, call, call_get_monologue); + struct call_monologue *ml = janus_get_monologue(handle_id, call, NULL, janus_call_get_monologue); if (ml) monologue_destroy(ml); diff --git a/daemon/redis.c b/daemon/redis.c index 103ac9b0c..39ff58b70 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -1557,7 +1557,7 @@ static int redis_tags(call_t *c, struct redis_list *tags, parser_arg arg) { for (i = 0; i < tags->len; i++) { rh = &tags->rh[i]; - ml = __monologue_create(c); + ml = __monologue_create(c, &c->callid); if (!ml) return -1; @@ -1565,6 +1565,8 @@ static int redis_tags(call_t *c, struct redis_list *tags, parser_arg arg) { return -1; if (!redis_hash_get_str(&s, rh, "tag")) __monologue_tag(ml, &s); + if (!redis_hash_get_str(&s, rh, "call_id")) + ml->call_id = call_str_cpy(&s); if (!redis_hash_get_str(&s, rh, "via-branch")) __monologue_viabranch(ml, &s); if (!redis_hash_get_str(&s, rh, "label")) @@ -2639,6 +2641,8 @@ static str redis_encode_json(ng_parser_ctx_t *ctx, call_t *c, void **to_free) { if (ml->tag.s) JSON_SET_SIMPLE_STR("tag", &ml->tag); + if (ml->call_id.s) + JSON_SET_SIMPLE_STR("call_id", &ml->tag); if (ml->viabranch.s) JSON_SET_SIMPLE_STR("via-branch", &ml->viabranch); if (ml->label.s) diff --git a/include/call.h b/include/call.h index 681448794..a695b9714 100644 --- a/include/call.h +++ b/include/call.h @@ -602,7 +602,8 @@ TYPED_GPTRARRAY(medias_arr, struct call_media) * A regular A/B call has two call_monologue objects with each subscribed to the other. */ struct call_monologue { - call_t *call; /* RO */ + call_t *call; /* RO */ + str call_id; // RO - in case of merged calls with ID aliases unsigned int unique_id; /* RO */ str tag; @@ -838,7 +839,9 @@ extern __thread call_t *call_memory_arena; int call_init(void); void call_free(void); -struct call_monologue *__monologue_create(call_t *call); +__attribute__((nonnull(1, 2))) +struct call_monologue *__monologue_create(call_t *call, const str *callid); + void __monologue_free(struct call_monologue *m); void __monologue_tag(struct call_monologue *ml, const str *tag); void __monologue_viabranch(struct call_monologue *ml, const str *viabranch); @@ -874,16 +877,25 @@ G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(subscription_q, media_subscriptions_clear) call_t *call_get_or_create(const str *callid, bool exclusive); call_t *call_get_opmode(const str *callid, enum ng_opmode opmode); void call_make_own_foreign(call_t *c, bool foreign); -int call_get_mono_dialogue(struct call_monologue *monologues[2], call_t *call, + +__attribute__((nonnull(1, 2, 3, 4))) +int call_get_mono_dialogue(struct call_monologue *monologues[2], + call_t *call, + const str *callid, const str *fromtag, const str *totag, const str *viabranch, sdp_ng_flags *, const endpoint_t *); + struct call_monologue *call_get_monologue(call_t *call, const str *fromtag); -struct call_monologue *call_get_or_create_monologue(call_t *call, const str *fromtag); + +__attribute__((nonnull(1, 2, 3))) +struct call_monologue *call_get_or_create_monologue(call_t *call, const str *callid, const str *fromtag); + __attribute__((nonnull(1, 2, 4, 5, 6))) struct call_media *call_make_transform_media(struct call_monologue *ml, const str *type, enum media_type type_id, const str *media_id, const endpoint_t *remote, const str *interface); + __attribute__((nonnull(1))) call_t *call_get(const str *callid); __attribute__((nonnull(1))) diff --git a/t/test-stats.c b/t/test-stats.c index 9a88227ab..0931dde51 100644 --- a/t/test-stats.c +++ b/t/test-stats.c @@ -5257,9 +5257,9 @@ int main(void) { const str callid1 = STR_CONST("test1"); const str callid2 = STR_CONST("test2"); call_t *call1 = call_get_or_create(&callid1, true); - struct call_monologue *ml1 = call_get_or_create_monologue(call1, &callid1); + struct call_monologue *ml1 = call_get_or_create_monologue(call1, &callid1, &callid1); call_t *call2 = call_get_or_create(&callid2, true); - struct call_monologue *ml2 = call_get_or_create_monologue(call2, &callid2); + struct call_monologue *ml2 = call_get_or_create_monologue(call2, &callid2, &callid2); call1->created = ml1->started = 157 * 1000000LL; call2->created = ml2->started = 57 * 1000000LL; diff --git a/t/test-transcode.c b/t/test-transcode.c index ab7d6af64..eee3a5390 100644 --- a/t/test-transcode.c +++ b/t/test-transcode.c @@ -101,8 +101,8 @@ static void __start(const char *file, int line) { call.callid = STR("test-call"); bencode_buffer_init(&call.buffer); call_memory_arena_set(&call); - ml_A = __monologue_create(&call); - ml_B = __monologue_create(&call); + ml_A = __monologue_create(&call, &call.callid); + ml_B = __monologue_create(&call, &call.callid); media_A = call_media_new(&call); // originator media_B = call_media_new(&call); // output destination t_queue_push_tail(&media_A->streams, ps_new(media_A));