From 5822cb889db804912da40776aaa4be76f5fa2a42 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 30 Mar 2023 09:31:10 -0400 Subject: [PATCH] MT#56447 change ml->medias to GPtrArray Using a pointer array instead of a linked lists allows us to directly reference a media section by index number, without having to spool into the linked list. No functional changes. Change-Id: I8b0e93f0c2e9addbcb4c938894118ed4a6aec768 --- daemon/call.c | 165 ++++++++++++++++----------------------- daemon/call_interfaces.c | 69 +++++++++------- daemon/cdr.c | 6 +- daemon/cli.c | 12 ++- daemon/codec.c | 29 +++---- daemon/janus.c | 16 ++-- daemon/media_player.c | 4 +- daemon/media_socket.c | 6 +- daemon/mqtt.c | 6 +- daemon/redis.c | 71 +++++++++++------ daemon/sdp.c | 35 ++++----- daemon/statistics.c | 8 +- include/call.h | 2 +- 13 files changed, 225 insertions(+), 204 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 11033530a..c0ebf368a 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -851,27 +851,14 @@ struct call_media *call_media_new(struct call *call) { return med; } -static struct call_media *__get_media(struct call_monologue *ml, GList **it, const struct stream_params *sp, - const struct sdp_ng_flags *flags, int index) +static struct call_media *__get_media(struct call_monologue *ml, const struct stream_params *sp, + const struct sdp_ng_flags *flags, unsigned int index) { struct call_media *med; struct call *call; - // is this a repeated call with *it set but for a different ml? - if (*it) { - med = (*it)->data; - if (med->monologue != ml) - *it = NULL; - } - - /* iterator points to last seen element, or NULL if uninitialized */ - if (!*it) - *it = ml->medias.head; - else - *it = (*it)->next; - // check for trickle ICE SDP fragment - if (flags && flags->fragment && sp->media_id.s) { + if (flags && flags->fragment && sp->media_id.len) { // in this case, the media sections are out of order and the media ID // string is used to determine which media section to operate on. this // info must be present and valid. @@ -883,18 +870,19 @@ static struct call_media *__get_media(struct call_monologue *ml, GList **it, con STR_FMT(&sp->media_id)); } - unsigned int want_index = sp->index; - if (index != -1) - want_index = index; + unsigned int want_index = index; + if (want_index == 0) + want_index = sp->index; + assert(want_index > 0); + unsigned int arr_index = want_index - 1; - /* possible incremental update, hunt for correct media struct */ - while (*it) { - med = (*it)->data; - if (med->index == want_index) { - __C_DBG("found existing call_media for stream #%u", want_index); - return med; - } - *it = (*it)->next; + // check if we have an existing media struct. resize array if needed + if (arr_index >= ml->medias->len) + g_ptr_array_set_size(ml->medias, want_index); + + if (ml->medias->pdata[arr_index]) { + __C_DBG("found existing call_media for stream #%u", want_index); + return ml->medias->pdata[arr_index]; } __C_DBG("allocating new call_media for stream #%u", want_index); @@ -905,9 +893,7 @@ static struct call_media *__get_media(struct call_monologue *ml, GList **it, con call_str_cpy(ml->call, &med->type, &sp->type); med->type_id = sp->type_id; - g_queue_push_tail(&ml->medias, med); - - *it = ml->medias.tail; + ml->medias->pdata[arr_index] = med; return med; } @@ -2772,26 +2758,12 @@ static void __update_init_subscribers(struct call_monologue *ml, GQueue *streams { GList *sl = streams ? streams->head : NULL; - // create media iterators for all subscribers - GList *sub_medias[ml->subscribers.length]; - struct sink_attrs attrs[ml->subscribers.length]; - unsigned int num_subs = 0; - for (GList *l = ml->subscribers.head; l; l = l->next) { - struct call_subscription *cs = l->data; - struct call_monologue *sub_ml = cs->monologue; - sub_medias[num_subs] = sub_ml->medias.head; - // skip into correct media section for multi-ml subscriptions - for (unsigned int offset = cs->media_offset; offset && sub_medias[num_subs]; offset--) - sub_medias[num_subs] = sub_medias[num_subs]->next; - attrs[num_subs] = cs->attrs; - num_subs++; - } - // keep num_subs as shortcut to ml->subscribers.length - recording_setup_monologue(ml); - for (GList *l = ml->medias.head; l; l = l->next) { - struct call_media *media = l->data; + for (unsigned int j = 0; j < ml->medias->len; j++) { + struct call_media *media = ml->medias->pdata[j]; + if (!media) + continue; struct stream_params *sp = NULL; if (sl) { @@ -2803,14 +2775,17 @@ static void __update_init_subscribers(struct call_monologue *ml, GQueue *streams // update all subscribers __reset_streams(media); - for (unsigned int i = 0; i < num_subs; i++) { - if (!sub_medias[i]) - continue; - struct call_media *sub_media = sub_medias[i]->data; - sub_medias[i] = sub_medias[i]->next; - - if (__init_streams(media, sub_media, sp, flags, &attrs[i])) + for (GList *l = ml->subscribers.head; l; l = l->next) { + struct call_subscription *cs = l->data; + struct call_monologue *sub_ml = cs->monologue; + unsigned int sub_media_idx = j + cs->media_offset; + if (sub_media_idx >= sub_ml->medias->len) + continue; + struct call_media *sub_media = sub_ml->medias->pdata[sub_media_idx]; + if (!sub_media) + continue; + if (__init_streams(media, sub_media, sp, flags, &cs->attrs)) ilog(LOG_WARN, "Error initialising streams"); } @@ -3039,8 +3014,6 @@ unsigned int proto_num_ports(unsigned int sp_ports, struct call_media *media, st int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, struct sdp_ng_flags *flags) { - struct stream_params *sp; - GList *media_iter, *ml_media, *other_ml_media; struct call_media *media, *other_media; struct endpoint_map *em; struct call_monologue *other_ml = dialogue[0]; @@ -3058,18 +3031,17 @@ int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, __C_DBG("this="STR_FORMAT" other="STR_FORMAT, STR_FMT(&monologue->tag), STR_FMT(&other_ml->tag)); - ml_media = other_ml_media = NULL; - set_transcoding_flag(monologue, other_ml, false); - for (media_iter = streams->head; media_iter; media_iter = media_iter->next) { - sp = media_iter->data; + for (GList *sp_iter = streams->head; sp_iter; sp_iter = sp_iter->next) { + struct stream_params *sp = sp_iter->data; __C_DBG("processing media stream #%u", sp->index); + assert(sp->index > 0); /* first, check for existence of call_media struct on both sides of * the dialogue */ - media = __get_media(monologue, &ml_media, sp, flags, -1); - other_media = __get_media(other_ml, &other_ml_media, sp, flags, -1); + media = __get_media(monologue, sp, flags, 0); + other_media = __get_media(other_ml, sp, flags, 0); /* OTHER is the side which has sent the message. SDP parameters in * "sp" are as advertised by OTHER side. The message will be sent to * THIS side. Parameters sent to THIS side may be overridden by @@ -3320,11 +3292,9 @@ struct call_subscription *call_get_call_subscription(GHashTable *ht, struct call int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_flags *flags) { __call_monologue_init_from_flags(ml, flags); - GList *media_iter = NULL; - for (GList *l = streams->head; l; l = l->next) { struct stream_params *sp = l->data; - struct call_media *media = __get_media(ml, &media_iter, sp, flags, -1); + struct call_media *media = __get_media(ml, sp, flags, 0); __media_init_from_flags(media, NULL, sp, flags); @@ -3381,15 +3351,15 @@ int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_ /* called with call->master_lock held in W */ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct call_monologue *dst_ml, - struct sdp_ng_flags *flags, GList **src_media_it, GList **dst_media_it, unsigned int *index) + struct sdp_ng_flags *flags, unsigned int *index) { unsigned int idx_diff = 0, rev_idx_diff = 0; for (GList *l = src_ml->last_in_sdp_streams.head; l; l = l->next) { struct stream_params *sp = l->data; - struct call_media *dst_media = __get_media(dst_ml, dst_media_it, sp, flags, (*index)++); - struct call_media *src_media = __get_media(src_ml, src_media_it, sp, flags, -1); + struct call_media *dst_media = __get_media(dst_ml, sp, flags, (*index)++); + struct call_media *src_media = __get_media(src_ml, sp, flags, 0); // track media index difference if one ml is subscribed to multiple other mls if (idx_diff == 0 && dst_media->index > src_media->index) @@ -3457,16 +3427,13 @@ int monologue_subscribe_request(const GQueue *srcs, struct call_monologue *dst_m __call_monologue_init_from_flags(dst_ml, flags); - GList *dst_media_it = NULL; - GList *src_media_it = NULL; unsigned int index = 1; // running counter for output/dst medias for (GList *sl = srcs->head; sl; sl = sl->next) { struct call_subscription *cs = sl->data; struct call_monologue *src_ml = cs->monologue; - int ret = monologue_subscribe_request1(src_ml, dst_ml, flags, &src_media_it, &dst_media_it, - &index); + int ret = monologue_subscribe_request1(src_ml, dst_ml, flags, &index); if (ret) return -1; } @@ -3475,8 +3442,6 @@ int monologue_subscribe_request(const GQueue *srcs, struct call_monologue *dst_m /* called with call->master_lock held in W */ int monologue_subscribe_answer(struct call_monologue *dst_ml, struct sdp_ng_flags *flags, GQueue *streams) { - GList *dst_media_it = NULL; - GList *src_media_it = NULL; GList *src_ml_it = dst_ml->subscriptions.head; unsigned int index = 1; // running counter for input/src medias @@ -3485,21 +3450,23 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, struct sdp_ng_flag for (GList *l = streams->head; l; l = l->next) { struct stream_params *sp = l->data; + struct call_subscription *cs = src_ml_it->data; + struct call_monologue *src_ml = cs->monologue; + // grab the matching source ml: // we need to move to the next one when we've reached the last media of // the current source ml - if (src_media_it && !src_media_it->next) { + if (index > src_ml->medias->len) { src_ml_it = src_ml_it->next; index = 1; // starts over at 1 + cs = src_ml_it->data; + src_ml = cs->monologue; } if (!src_ml_it) return -1; - struct call_subscription *cs = src_ml_it->data; - struct call_monologue *src_ml = cs->monologue; - - struct call_media *dst_media = __get_media(dst_ml, &dst_media_it, sp, flags, -1); - struct call_media *src_media = __get_media(src_ml, &src_media_it, sp, flags, index++); + struct call_media *dst_media = __get_media(dst_ml, sp, flags, 0); + struct call_media *src_media = __get_media(src_ml, sp, flags, index++); if (__media_init_from_flags(dst_media, NULL, sp, flags) == 1) continue; @@ -3762,8 +3729,10 @@ void call_destroy(struct call *c) { STR_FMT_M(&csm->tag)); } - for (k = ml->medias.head; k; k = k->next) { - md = k->data; + for (unsigned int m = 0; m < ml->medias->len; m++) { + md = ml->medias->pdata[m]; + if (!md) + continue; // stats output only - no cleanups @@ -3951,7 +3920,7 @@ static void __call_free(void *p) { while (c->monologues.head) { m = g_queue_pop_head(&c->monologues); - g_queue_clear(&m->medias); + g_ptr_array_free(m->medias, true); g_hash_table_destroy(m->associated_tags); g_hash_table_destroy(m->media_ids); free_ssrc_hash(&m->ssrc_hash); @@ -4154,12 +4123,12 @@ struct call_monologue *__monologue_create(struct call *call) { ret->call = call; ret->created = rtpe_now.tv_sec; ret->associated_tags = g_hash_table_new(g_direct_hash, g_direct_equal); + ret->medias = g_ptr_array_new(); ret->media_ids = g_hash_table_new(str_hash, str_equal); ret->ssrc_hash = create_ssrc_hash_call(); ret->subscribers_ht = g_hash_table_new(g_direct_hash, g_direct_equal); ret->subscriptions_ht = g_hash_table_new(g_direct_hash, g_direct_equal); - g_queue_init(&ret->medias); gettimeofday(&ret->started, NULL); return ret; @@ -4203,18 +4172,16 @@ static void __unconfirm_sinks(GQueue *q) { } /* must be called with call->master_lock held in W */ void __monologue_unkernelize(struct call_monologue *monologue) { - GList *l, *m; - struct call_media *media; - struct packet_stream *stream; - if (!monologue) return; - for (l = monologue->medias.head; l; l = l->next) { - media = l->data; + for (unsigned int i = 0; i < monologue->medias->len; i++) { + struct call_media *media = monologue->medias->pdata[i]; + if (!media) + continue; - for (m = media->streams.head; m; m = m->next) { - stream = m->data; + for (GList *m = media->streams.head; m; m = m->next) { + struct packet_stream *stream = m->data; __stream_unconfirm(stream); __unconfirm_sinks(&stream->rtp_sinks); __unconfirm_sinks(&stream->rtcp_sinks); @@ -4280,8 +4247,10 @@ void monologue_destroy(struct call_monologue *monologue) { g_hash_table_remove(call->viabranches, &monologue->viabranch); // close sockets - for (GList *l = monologue->medias.head; l; l = l->next) { - struct call_media *m = l->data; + for (unsigned int i = 0; i < monologue->medias->len; i++) { + struct call_media *m = monologue->medias->pdata[i]; + if (!m) + continue; for (GList *k = m->streams.head; k; k = k->next) { struct packet_stream *ps = k->data; if (ps->selected_sfd && ps->selected_sfd->socket.local.port) @@ -4603,6 +4572,8 @@ int call_get_mono_dialogue(struct call_monologue *dialogue[2], struct call *call static void media_stop(struct call_media *m) { + if (!m) + return; t38_gateway_stop(m->t38_gateway); audio_player_stop(m); codec_handlers_stop(&m->codec_handlers_store); @@ -4614,8 +4585,8 @@ static void __monologue_stop(struct call_monologue *ml) { } static void monologue_stop(struct call_monologue *ml) { __monologue_stop(ml); - for (GList *l = ml->medias.head; l; l = l->next) - media_stop(l->data); + for (unsigned int i = 0; i < ml->medias->len; i++) + media_stop(ml->medias->pdata[i]); } diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index cce09e7c4..8ccf00ae5 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -72,10 +72,9 @@ static int call_stream_address_gstring(GString *o, struct packet_stream *ps, enu return ret; } -static str *streams_print(GQueue *s, int start, int end, const char *prefix, enum stream_address_format format) { +static str *streams_print(GPtrArray *s, int start, int end, const char *prefix, enum stream_address_format format) { GString *o; int i, af, port; - GList *l; struct call_media *media; struct packet_stream *ps; @@ -84,18 +83,14 @@ static str *streams_print(GQueue *s, int start, int end, const char *prefix, enu g_string_append_printf(o, "%s ", prefix); for (i = start; i <= end; i++) { - for (l = s->head; l; l = l->next) { - media = l->data; - if (media->index == i) - goto found; + if (s->len <= i || (media = s->pdata[i - 1]) == NULL) { + ilog(LOG_WARNING, "Requested media index %i not found", i); + break; } - ilog(LOG_WARNING, "Requested media index %i not found", i); - goto out; -found: if (!media->streams.head) { ilog(LOG_WARNING, "Media has no streams"); - goto out; + break; } ps = media->streams.head->data; @@ -112,7 +107,6 @@ found: } -out: g_string_append(o, "\n"); return g_string_free_str(o); @@ -222,7 +216,7 @@ 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(dialogue[1]->medias, sp.index, sp.index, out[RE_UDP_COOKIE], SAF_UDP); rwlock_unlock_w(&c->master_lock); @@ -364,7 +358,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]->medias, 1, s.length, NULL, SAF_TCP); out2: call_unlock_release_update(&c); @@ -2416,7 +2410,6 @@ static void ng_stats_monologue(bencode_item_t *dict, const struct call_monologue struct call_stats *totals, bencode_item_t *ssrc) { bencode_item_t *sub, *medias = NULL; - GList *l; struct call_media *m; if (!ml) @@ -2458,8 +2451,10 @@ static void ng_stats_monologue(bencode_item_t *dict, const struct call_monologue medias = bencode_dictionary_add_list(sub, "medias"); stats: - for (l = ml->medias.head; l; l = l->next) { - m = l->data; + for (unsigned int i = 0; i < ml->medias->len; i++) { + m = ml->medias->pdata[i]; + if (!m) + continue; ng_stats_media(medias, m, totals); } } @@ -2745,8 +2740,10 @@ static const char *media_block_match1(struct call *call, struct call_monologue * // walk our structures to find a matching stream for (GList *l = call->monologues.head; l; l = l->next) { *monologue = l->data; - for (GList *k = (*monologue)->medias.head; k; k = k->next) { - struct call_media *media = k->data; + for (unsigned int k = 0; k < (*monologue)->medias->len; k++) { + struct call_media *media = (*monologue)->medias->pdata[k]; + if (!media) + continue; if (!media->streams.head) continue; struct packet_stream *ps = media->streams.head->data; @@ -2921,8 +2918,10 @@ const char *call_stop_forwarding_ng(bencode_item_t *input, bencode_item_t *outpu static void call_monologue_set_block_mode(struct call_monologue *ml, struct sdp_ng_flags *flags) { if (flags->delay_buffer >= 0) { - for (GList *l = ml->medias.head; l; l = l->next) { - struct call_media *media = l->data; + for (unsigned int i = 0; i < ml->medias->len; i++) { + struct call_media *media = ml->medias->pdata[i]; + if (!media) + continue; media->buffer_delay = flags->delay_buffer; } } @@ -3018,8 +3017,10 @@ const char *call_unblock_dtmf_ng(bencode_item_t *input, bencode_item_t *output) monologue->block_dtmf = BLOCK_DTMF_OFF; if (is_dtmf_replace_mode(prev_mode) || flags.delay_buffer >= 0) { if (flags.delay_buffer >= 0) { - for (GList *l = monologue->medias.head; l; l = l->next) { - struct call_media *media = l->data; + for (unsigned int i = 0; i < monologue->medias->len; i++) { + struct call_media *media = monologue->medias->pdata[i]; + if (!media) + continue; media->buffer_delay = flags.delay_buffer; } } @@ -3040,8 +3041,10 @@ const char *call_unblock_dtmf_ng(bencode_item_t *input, bencode_item_t *output) monologue->block_dtmf = BLOCK_DTMF_OFF; } if (flags.delay_buffer >= 0) { - for (GList *k = monologue->medias.head; k; k = k->next) { - struct call_media *media = k->data; + for (unsigned int i = 0; i < monologue->medias->len; i++) { + struct call_media *media = monologue->medias->pdata[i]; + if (!media) + continue; media->buffer_delay = flags.delay_buffer; } } @@ -3344,8 +3347,10 @@ const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { // find a usable output media struct call_media *media; - for (GList *l = monologue->medias.head; l; l = l->next) { - media = l->data; + for (unsigned int i = 0; i < monologue->medias->len; i++) { + media = monologue->medias->pdata[i]; + if (!media) + continue; if (media->type_id != MT_AUDIO) continue; goto found; @@ -3359,8 +3364,10 @@ found: struct call_subscription *cs = k->data; struct call_monologue *dialogue = cs->monologue; struct call_media *sink = NULL; - for (GList *m = dialogue->medias.head; m; m = m->next) { - sink = m->data; + for (unsigned int i = 0; i < dialogue->medias->len; i++) { + sink = dialogue->medias->pdata[i]; + if (!sink) + continue; if (sink->type_id != MT_AUDIO) continue; goto found_sink; @@ -3531,8 +3538,10 @@ const char *call_subscribe_request_ng(bencode_item_t *input, bencode_item_t *out if (source_ml->label.len) bencode_dictionary_add_str(tag_label, "label", &source_ml->label); bencode_item_t *medias = bencode_dictionary_add_list(tag_label, "medias"); - for (GList *k = source_ml->medias.head; k; k = k->next) { - struct call_media *media = k->data; + for (unsigned int i = 0; i < source_ml->medias->len; i++) { + struct call_media *media = source_ml->medias->pdata[i]; + if (!media) + continue; bencode_item_t *med_ent = bencode_list_add_dictionary(medias); bencode_dictionary_add_integer(med_ent, "index", media->index); bencode_dictionary_add_str(med_ent, "type", &media->type); diff --git a/daemon/cdr.c b/daemon/cdr.c index 1e8f10e4d..33989c961 100644 --- a/daemon/cdr.c +++ b/daemon/cdr.c @@ -90,8 +90,10 @@ void cdr_update_entry(struct call* c) { } } - for (k = ml->medias.head; k; k = k->next) { - md = k->data; + for (unsigned int i = 0; i < ml->medias->len; i++) { + md = ml->medias->pdata[i]; + if (!md) + continue; rtp_pt = __rtp_stats_codec(md); diff --git a/daemon/cli.c b/daemon/cli.c index 2db4f3171..e682e3a2b 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -671,8 +671,10 @@ static void cli_list_tag_info(struct cli_writer *cw, struct call_monologue *ml) STR_FMT_M(&csm->tag)); } - for (GList *k = ml->medias.head; k; k = k->next) { - md = k->data; + for (unsigned int k = 0; k < ml->medias->len; k++) { + md = ml->medias->pdata[k]; + if (!md) + continue; const struct rtp_payload_type *rtp_pt = __rtp_stats_codec(md); @@ -1586,8 +1588,10 @@ static void cli_incoming_tag_delay(str *instr, struct cli_writer *cw) { cw->cw_printf(cw, "Setting delay to %i\n", delay); - for (GList *l = cw->ml->medias.head; l; l = l->next) { - struct call_media *m = l->data; + for (unsigned int k = 0; k < cw->ml->medias->len; k++) { + struct call_media *m = cw->ml->medias->pdata[k]; + if (!m) + continue; m->buffer_delay = delay; } codec_update_all_handlers(cw->ml); diff --git a/daemon/codec.c b/daemon/codec.c index 1c31730bb..79448c8fc 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -3996,14 +3996,14 @@ void codec_update_all_handlers(struct call_monologue *ml) { struct call_monologue *sink = cs->monologue; // iterate both simultaneously - GList *source_media_it = ml->medias.head; - GList *sink_media_it = sink->medias.head; - while (source_media_it && sink_media_it) { - struct call_media *source_media = source_media_it->data; - struct call_media *sink_media = sink_media_it->data; + for (unsigned int i = 0; i < ml->medias->len && i < sink->medias->len; i++) { + struct call_media *source_media = ml->medias->pdata[i]; + if (!source_media) + continue; + struct call_media *sink_media = sink->medias->pdata[i]; + if (!sink_media) + continue; codec_handlers_update(source_media, sink_media, NULL, NULL); - source_media_it = source_media_it->next; - sink_media_it = sink_media_it->next; } } @@ -4015,14 +4015,15 @@ void codec_update_all_source_handlers(struct call_monologue *ml, const struct sd struct call_monologue *source = cs->monologue; // iterate both simultaneously - GList *source_media_it = source->medias.head; - GList *sink_media_it = ml->medias.head; - while (source_media_it && sink_media_it) { - struct call_media *source_media = source_media_it->data; - struct call_media *sink_media = sink_media_it->data; + + for (unsigned int i = 0; i < source->medias->len && i < ml->medias->len; i++) { + struct call_media *source_media = source->medias->pdata[i]; + if (!source_media) + continue; + struct call_media *sink_media = ml->medias->pdata[i]; + if (!sink_media) + continue; codec_handlers_update(source_media, sink_media, flags, NULL); - source_media_it = source_media_it->next; - sink_media_it = sink_media_it->next; } } diff --git a/daemon/janus.c b/daemon/janus.c index 42e7de316..129b3f705 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -307,8 +307,10 @@ static void janus_add_publisher_details(JsonBuilder *builder, struct call_monolo const char *a_codec = NULL, *v_codec = NULL; - for (GList *l = ml->medias.head; l; l = l->next) { - struct call_media *media = l->data; + for (unsigned int i = 0; i < ml->medias->len; i++) { + struct call_media *media = ml->medias->pdata[i]; + if (!media) + continue; const char *codec = NULL; for (GList *k = media->codecs.codec_prefs.head; k; k = k->next) { @@ -877,8 +879,10 @@ static const char *janus_videoroom_configure(struct websocket_message *wm, struc json_builder_add_string_value(builder, "ok"); // apply audio/video bool flags - for (GList *l = ml->medias.head; l; l = l->next) { - struct call_media *media = l->data; + for (unsigned int i = 0; i < ml->medias->len; i++) { + struct call_media *media = ml->medias->pdata[i]; + if (!media) + continue; if (media->type_id == MT_AUDIO) { if (has_audio == 0) @@ -1555,8 +1559,8 @@ const char *janus_trickle(JsonReader *reader, struct janus_session *session, uin str sdp_mid_str = STR_CONST_INIT_LEN((char *) sdp_mid, strlen(sdp_mid)); media = g_hash_table_lookup(ml->media_ids, &sdp_mid_str); } - if (!media && sdp_m_line >= 0) - media = g_queue_peek_nth(&ml->medias, sdp_m_line); + if (!media && sdp_m_line >= 0 && ml->medias->len > sdp_m_line) + media = ml->medias->pdata[sdp_m_line]; *retcode = 466; if (!media) diff --git a/daemon/media_player.c b/daemon/media_player.c index a0655f897..dec1677af 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -887,8 +887,8 @@ static const struct rtp_payload_type *media_player_play_init(struct media_player // find call media suitable for playback struct call_media *media; - for (GList *l = mp->ml->medias.head; l; l = l->next) { - media = l->data; + for (unsigned int i = 0; i < mp->ml->medias->len; i++) { + media = mp->ml->medias->pdata[i]; if (media->type_id != MT_AUDIO) continue; if (!MEDIA_ISSET(media, SEND)) diff --git a/daemon/media_socket.c b/daemon/media_socket.c index c2d195485..53bee6b1b 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -2907,8 +2907,10 @@ out: for (GList *l = phc->mp.media->monologue->subscriptions.head; l; l = l->next) { struct call_subscription *cs = l->data; struct call_monologue *sub = cs->monologue; - for (GList *k = sub->medias.head; k; k = k->next) { - struct call_media *sub_media = k->data; + for (unsigned int k = 0; k < sub->medias->len; k++) { + struct call_media *sub_media = sub->medias->pdata[k]; + if (!sub_media) + continue; for (GList *m = sub_media->streams.head; m; m = m->next) { struct packet_stream *sub_ps = m->data; __unkernelize(sub_ps); diff --git a/daemon/mqtt.c b/daemon/mqtt.c index 37c428564..31a1bce72 100644 --- a/daemon/mqtt.c +++ b/daemon/mqtt.c @@ -446,8 +446,10 @@ static void mqtt_full_call(struct call *call, JsonBuilder *json) { json_builder_set_member_name(json, "medias"); json_builder_begin_array(json); - for (GList *k = ml->medias.head; k; k = k->next) { - struct call_media *media = k->data; + for (unsigned int k = 0; k < ml->medias->len; k++) { + struct call_media *media = ml->medias->pdata[k]; + if (!media) + continue; json_builder_begin_object(json); mqtt_media_stats(media, json); json_builder_end_object(json); diff --git a/daemon/redis.c b/daemon/redis.c index 4a0f91f65..bc881ccfd 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -34,6 +34,14 @@ #include "main.h" #include "codec.h" + +typedef union { + GQueue *q; + GPtrArray *pa; + void *v; +} callback_arg_t; + + struct redis *rtpe_redis; struct redis *rtpe_redis_write; struct redis *rtpe_redis_write_disabled; @@ -1198,9 +1206,9 @@ static void *redis_list_get_ptr(struct redis_list *list, struct redis_hash *rh, return redis_list_get_idx_ptr(list, idx); } -static int json_build_list_cb(GQueue *q, struct call *c, const char *key, +static int json_build_list_cb(callback_arg_t q, struct call *c, const char *key, unsigned int idx, struct redis_list *list, - int (*cb)(str *, GQueue *, struct redis_list *, void *), void *ptr, JsonReader *root_reader) + int (*cb)(str *, callback_arg_t, struct redis_list *, void *), void *ptr, JsonReader *root_reader) { char key_concatted[256]; @@ -1233,17 +1241,34 @@ static int json_build_list_cb(GQueue *q, struct call *c, const char *key, return 0; } -static int rbl_cb_simple(str *s, GQueue *q, struct redis_list *list, void *ptr) { +static int rbl_cb_simple(str *s, callback_arg_t qp, struct redis_list *list, void *ptr) { + GQueue *q = qp.q; int j; j = str_to_i(s, 0); g_queue_push_tail(q, redis_list_get_idx_ptr(list, (unsigned) j)); return 0; } +static int rbpa_cb_simple(str *s, callback_arg_t pap, struct redis_list *list, void *ptr) { + GPtrArray *pa = pap.pa; + int j; + j = str_to_i(s, 0); + if (pa->len <= j) + g_ptr_array_set_size(pa, j + 1); + pa->pdata[j] = redis_list_get_idx_ptr(list, (unsigned) j); + return 0; +} + static int json_build_list(GQueue *q, struct call *c, const char *key, unsigned int idx, struct redis_list *list, JsonReader *root_reader) { - return json_build_list_cb(q, c, key, idx, list, rbl_cb_simple, NULL, root_reader); + return json_build_list_cb((callback_arg_t) q, c, key, idx, list, rbl_cb_simple, NULL, root_reader); +} + +static int json_build_ptra(GPtrArray *q, struct call *c, const char *key, + unsigned int idx, struct redis_list *list, JsonReader *root_reader) +{ + return json_build_list_cb((callback_arg_t) q, c, key, idx, list, rbpa_cb_simple, NULL, root_reader); } static int json_get_list_hash(struct redis_list *out, @@ -1500,7 +1525,7 @@ static int redis_tags(struct call *c, struct redis_list *tags, JsonReader *root_ return 0; } -static struct rtp_payload_type *rbl_cb_plts_g(str *s, GQueue *q, struct redis_list *list, void *ptr) { +static struct rtp_payload_type *rbl_cb_plts_g(str *s, struct redis_list *list, void *ptr) { str ptype; struct call_media *med = ptr; @@ -1515,9 +1540,9 @@ static struct rtp_payload_type *rbl_cb_plts_g(str *s, GQueue *q, struct redis_li return pt; } -static int rbl_cb_plts_r(str *s, GQueue *q, struct redis_list *list, void *ptr) { +static int rbl_cb_plts_r(str *s, callback_arg_t dummy, struct redis_list *list, void *ptr) { struct call_media *med = ptr; - codec_store_add_raw(&med->codecs, rbl_cb_plts_g(s, q, list, ptr)); + codec_store_add_raw(&med->codecs, rbl_cb_plts_g(s, list, ptr)); return 0; } static int json_medias(struct call *c, struct redis_list *medias, JsonReader *root_reader) { @@ -1567,7 +1592,7 @@ static int json_medias(struct call *c, struct redis_list *medias, JsonReader *ro if (redis_hash_get_sdes_params(&med->sdes_out, rh, "sdes_out") < 0) return -1; - json_build_list_cb(NULL, c, "payload_types", i, NULL, rbl_cb_plts_r, med, root_reader); + json_build_list_cb((callback_arg_t) NULL, c, "payload_types", i, NULL, rbl_cb_plts_r, med, root_reader); /* XXX dtls */ medias->ptrs[i] = med; @@ -1628,7 +1653,7 @@ static int redis_link_sfds(struct redis_list *sfds, struct redis_list *streams) return 0; } -static int rbl_subs_cb(str *s, GQueue *q, struct redis_list *list, void *ptr) { +static int rbl_subs_cb(str *s, callback_arg_t dummy, struct redis_list *list, void *ptr) { str token; if (str_token_sep(&token, s, '/')) @@ -1677,7 +1702,7 @@ static int json_link_tags(struct call *c, struct redis_list *tags, struct redis_ for (i = 0; i < tags->len; i++) { ml = tags->ptrs[i]; - if (!json_build_list_cb(NULL, c, "subscriptions", i, tags, rbl_subs_cb, ml, root_reader)) { + if (!json_build_list_cb((callback_arg_t) NULL, c, "subscriptions", i, tags, rbl_subs_cb, ml, root_reader)) { // new format, ok ; } @@ -1721,7 +1746,7 @@ static int json_link_tags(struct call *c, struct redis_list *tags, struct redis_ } g_queue_clear(&q); - if (json_build_list(&ml->medias, c, "medias", i, medias, root_reader)) + if (json_build_ptra(ml->medias, c, "medias", i, medias, root_reader)) return -1; } @@ -1811,11 +1836,8 @@ static int json_link_streams(struct call *c, struct redis_list *streams, static int json_link_medias(struct call *c, struct redis_list *medias, struct redis_list *streams, struct redis_list *maps, struct redis_list *tags, JsonReader *root_reader) { - unsigned int i; - struct call_media *med; - - for (i = 0; i < medias->len; i++) { - med = medias->ptrs[i]; + for (unsigned int i = 0; i < medias->len; i++) { + struct call_media *med = medias->ptrs[i]; med->monologue = redis_list_get_ptr(tags, &medias->rh[i], "tag"); if (!med->monologue) @@ -1833,8 +1855,10 @@ static int json_link_medias(struct call *c, struct redis_list *medias, for (GList *sub = ml->subscriptions.head; sub; sub = sub->next) { struct call_subscription *cs = sub->data; struct call_monologue *other_ml = cs->monologue; - for (GList *l = other_ml->medias.head; l; l = l->next) { - struct call_media *other_m = l->data; + for (unsigned int j = 0; j < other_ml->medias->len; j++) { + struct call_media *other_m = other_ml->medias->pdata[j]; + if (!other_m) + continue; other_m->monologue = other_ml; if (other_m->index == med->index) { codec_handlers_update(med, other_m, NULL, NULL); @@ -1846,7 +1870,8 @@ static int json_link_medias(struct call *c, struct redis_list *medias, return 0; } -static int rbl_cb_intf_sfds(str *s, GQueue *q, struct redis_list *list, void *ptr) { +static int rbl_cb_intf_sfds(str *s, callback_arg_t qp, struct redis_list *list, void *ptr) { + GQueue *q = qp.q; int i; struct intf_list *il; struct endpoint_map *em; @@ -1884,7 +1909,7 @@ static int json_link_maps(struct call *c, struct redis_list *maps, for (i = 0; i < maps->len; i++) { em = maps->ptrs[i]; - if (json_build_list_cb(&em->intf_sfds, c, "map_sfds", em->unique_id, sfds, + if (json_build_list_cb((callback_arg_t) &em->intf_sfds, c, "map_sfds", em->unique_id, sfds, rbl_cb_intf_sfds, em, root_reader)) return -1; } @@ -2501,8 +2526,10 @@ char* redis_encode_json(struct call *c) { snprintf(tmp, sizeof(tmp), "medias-%u", ml->unique_id); json_builder_set_member_name(builder, tmp); json_builder_begin_array (builder); - for (k = ml->medias.head; k; k = k->next) { - media = k->data; + for (unsigned int j = 0; j < ml->medias->len; j++) { + media = ml->medias->pdata[j]; + if (!media) + continue; JSON_ADD_STRING("%u", media->unique_id); } json_builder_end_array(builder); diff --git a/daemon/sdp.c b/daemon/sdp.c index c746f2069..50d2d66e9 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -3132,28 +3132,26 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu { struct sdp_session *session; struct sdp_media *sdp_media; - GList *l, *k, *m, *rtp_ps_link; - int media_index, sess_conn; + GList *l, *k, *rtp_ps_link; + int sess_conn; struct call_media *call_media; struct packet_stream *ps; const char *err = NULL; - m = monologue->medias.head; - media_index = 1; + unsigned int media_index = 0; struct sdp_manipulations_common *sdp_manipulations = flags->sdp_manipulations; for (l = sessions->head; l; l = l->next) { session = l->data; - err = "no matching session media"; - if (!m) - goto error; // look for first usable (non-rejected, non-empty) packet stream // from any media to determine session-level attributes, if any ps = NULL; - for (GList *mc = m; mc; mc = mc->next) { - call_media = mc->data; + for (unsigned int ix = media_index; ix < monologue->medias->len; ix++) { + call_media = monologue->medias->pdata[ix]; + if (!call_media) + continue; if (!call_media->streams.head) continue; ps = call_media->streams.head->data; @@ -3255,11 +3253,8 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu } err = "no matching media"; - if (!m) - goto error; - call_media = m->data; - err = "media index mismatched"; - if (call_media->index != media_index) + call_media = monologue->medias->pdata[media_index]; + if (!call_media) goto error; err = "no matching media stream"; rtp_ps_link = call_media->streams.head; @@ -3323,7 +3318,6 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu sdp_manipulations_add(chop, sdp_manipulations, sdp_media->media_type_id); media_index++; - m = m->next; } } @@ -3350,11 +3344,11 @@ int sdp_create(str *out, struct call_monologue *monologue, struct sdp_ng_flags * GString *s = NULL; err = "Need at least one media"; - if (!monologue->medias.length) + if (!monologue->medias->len) goto err; // grab first components - struct call_media *media = monologue->medias.head->data; + struct call_media *media = monologue->medias->pdata[0]; err = "No media stream"; if (!media->streams.length) goto err; @@ -3378,8 +3372,11 @@ int sdp_create(str *out, struct call_monologue *monologue, struct sdp_ng_flags * g_string_append_printf(s, "s=%s\r\n", rtpe_config.software_id); g_string_append(s, "t=0 0\r\n"); - for (GList *l = monologue->medias.head; l; l = l->next) { - media = l->data; + for (unsigned int i = 0; i < monologue->medias->len; i++) { + media = monologue->medias->pdata[i]; + err = "Empty media stream"; + if (!media) + continue; err = "Zero length media stream"; if (!media->streams.length) goto err; diff --git a/daemon/statistics.c b/daemon/statistics.c index 3388424d9..bee446b4e 100644 --- a/daemon/statistics.c +++ b/daemon/statistics.c @@ -119,7 +119,7 @@ void statistics_update_foreignown_inc(struct call* c) { void statistics_update_oneway(struct call* c) { struct call_monologue *ml; struct call_media *md; - GList *k, *o; + GList *o; GList *l; if (IS_OWN_CALL(c)) { @@ -131,8 +131,10 @@ void statistics_update_oneway(struct call* c) { ml = l->data; // --- go through partner ml and search the RTP - for (k = ml->medias.head; k; k = k->next) { - md = k->data; + for (unsigned int i = 0; i < ml->medias->len; i++) { + md = ml->medias->pdata[i]; + if (!md) + continue; for (o = md->streams.head; o; o = o->next) { ps = o->data; diff --git a/include/call.h b/include/call.h index 6ab5408fc..d61e8c15c 100644 --- a/include/call.h +++ b/include/call.h @@ -505,7 +505,7 @@ struct call_monologue { GHashTable *subscriptions_ht; /* for quick lookup */ GQueue subscribers; /* who is subscribed to me (sinks) */ GHashTable *subscribers_ht; /* for quick lookup */ - GQueue medias; + GPtrArray *medias; GHashTable *media_ids; struct media_player *player; unsigned long long sdp_session_id;